From 9e2a58cd4dcd6c30ce4bc3b3dc02dbd2b7b4796a Mon Sep 17 00:00:00 2001 From: Sangbum Kim Date: Thu, 27 Apr 2017 23:30:52 +0900 Subject: [PATCH] initial commit --- .gitignore | 130 + Makefile | 61 + README.md | 98 + asset/static/images/ajax-loader.gif | Bin 0 -> 3208 bytes asset/static/images/ajax-loader.svg | 12 + asset/static/images/ajax-loader.webp | Bin 0 -> 5456 bytes asset/static/images/bug.png | Bin 0 -> 42503 bytes asset/static/images/favicon.144.png | Bin 0 -> 16766 bytes asset/static/images/favicon.152.png | Bin 0 -> 18033 bytes asset/static/images/favicon.16.png | Bin 0 -> 1542 bytes asset/static/images/favicon.24.png | Bin 0 -> 1683 bytes asset/static/images/favicon.32.png | Bin 0 -> 2423 bytes asset/static/images/favicon.48.png | Bin 0 -> 4232 bytes asset/static/images/favicon.64.png | Bin 0 -> 5931 bytes asset/static/images/favicon.ico | Bin 0 -> 34494 bytes asset/static/javascripts/common/blockui.js | 33 + asset/static/javascripts/common/dep.js | 102 + asset/static/javascripts/common/initial.js | 34 + asset/static/javascripts/common/mixed.js | 26 + asset/static/javascripts/widgets/modal.js | 20 + .../backbone-bootstrap-modal.js | 284 + .../backbone.computedfields.js | 136 + .../backbone.computedfields.min.js | 1 + asset/static/libs/requirejs-svg-0.0.1/svg.js | 75 + .../libs/requirejs-svg-0.0.1/svg.min.js | 3 + .../static/libs/select2-4.0.3/css/select2.css | 484 ++ .../libs/select2-4.0.3/css/select2.min.css | 1 + asset/static/libs/select2-4.0.3/js/i18n/ar.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/az.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/bg.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ca.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/cs.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/da.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/de.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/el.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/en.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/es.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/et.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/eu.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/fa.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/fi.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/fr.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/gl.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/he.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/hi.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/hr.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/hu.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/id.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/is.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/it.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ja.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/km.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ko.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/lt.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/lv.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/mk.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ms.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/nb.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/nl.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/pl.js | 3 + .../libs/select2-4.0.3/js/i18n/pt-BR.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/pt.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ro.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/ru.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/sk.js | 3 + .../libs/select2-4.0.3/js/i18n/sr-Cyrl.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/sr.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/sv.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/th.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/tr.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/uk.js | 3 + asset/static/libs/select2-4.0.3/js/i18n/vi.js | 3 + .../libs/select2-4.0.3/js/i18n/zh-CN.js | 3 + .../libs/select2-4.0.3/js/i18n/zh-TW.js | 3 + .../libs/select2-4.0.3/js/select2.full.js | 6436 +++++++++++++++++ .../libs/select2-4.0.3/js/select2.full.min.js | 3 + asset/static/libs/select2-4.0.3/js/select2.js | 5725 +++++++++++++++ .../libs/select2-4.0.3/js/select2.min.js | 3 + asset/static/stylesheets/common/custom.css | 217 + asset/static/stylesheets/common/modern.css | 2402 ++++++ .../static/stylesheets/common/modern.min.css | 1 + asset/static/views/widgets/modal.html | 21 + asset/template/layout/base.html | 77 + asset/template/views/base.html | 83 + asset/template/views/change_password.html | 116 + asset/template/views/error.html | 17 + asset/template/views/index.html | 14 + asset/template/views/login.html | 111 + bench.py | 36 + changer-dev.service | 28 + enums/user_type.go | 47 + http/iface/metric_count.go | 64 + http/iface/metric_duration.go | 118 + http/iface/rest.go | 236 + http/iface/rest_easyjson.go | 2330 ++++++ http/init.go | 116 + http/middleware/logging/middleware.go | 154 + http/middleware/recovery/middleware.go | 203 + http/middleware/secure/middleware.go | 179 + http/middleware/session/data.go | 60 + http/middleware/session/middleware.go | 121 + http/middleware/session/role.go | 62 + http/profile.go | 69 + http/route/change_password.go | 65 + http/route/index.go | 16 + http/route/login.go | 82 + http/route/services.go | 41 + http/route/static.go | 37 + http/template/loader.go | 60 + http/template/renderer.go | 59 + main.go | 143 + settings.yml | 32 + util/config.go | 84 + util/crypt/aes.go | 170 + util/crypt/common.go | 5 + util/crypt/password.go | 71 + util/daemon.go | 16 + util/iface/bytes16.go | 93 + util/iface/bytes32.go | 94 + util/iface/bytes64.go | 93 + util/iface/serialize.go | 22 + util/iface/uuid.go | 102 + util/json.go | 92 + util/ldap/ldap.go | 410 ++ util/logger.go | 73 + util/parse.go | 138 + util/tool.go | 313 + 127 files changed, 23001 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 asset/static/images/ajax-loader.gif create mode 100644 asset/static/images/ajax-loader.svg create mode 100644 asset/static/images/ajax-loader.webp create mode 100644 asset/static/images/bug.png create mode 100644 asset/static/images/favicon.144.png create mode 100644 asset/static/images/favicon.152.png create mode 100644 asset/static/images/favicon.16.png create mode 100644 asset/static/images/favicon.24.png create mode 100644 asset/static/images/favicon.32.png create mode 100644 asset/static/images/favicon.48.png create mode 100644 asset/static/images/favicon.64.png create mode 100644 asset/static/images/favicon.ico create mode 100644 asset/static/javascripts/common/blockui.js create mode 100644 asset/static/javascripts/common/dep.js create mode 100644 asset/static/javascripts/common/initial.js create mode 100644 asset/static/javascripts/common/mixed.js create mode 100644 asset/static/javascripts/widgets/modal.js create mode 100755 asset/static/libs/backbone-bootstrap-modal/backbone-bootstrap-modal.js create mode 100644 asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.js create mode 100644 asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.min.js create mode 100644 asset/static/libs/requirejs-svg-0.0.1/svg.js create mode 100644 asset/static/libs/requirejs-svg-0.0.1/svg.min.js create mode 100644 asset/static/libs/select2-4.0.3/css/select2.css create mode 100644 asset/static/libs/select2-4.0.3/css/select2.min.css create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ar.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/az.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/bg.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ca.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/cs.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/da.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/de.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/el.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/en.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/es.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/et.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/eu.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/fa.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/fi.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/fr.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/gl.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/he.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/hi.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/hr.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/hu.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/id.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/is.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/it.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ja.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/km.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ko.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/lt.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/lv.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/mk.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ms.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/nb.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/nl.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/pl.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/pt-BR.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/pt.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ro.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/ru.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/sk.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/sr-Cyrl.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/sr.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/sv.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/th.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/tr.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/uk.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/vi.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/zh-CN.js create mode 100644 asset/static/libs/select2-4.0.3/js/i18n/zh-TW.js create mode 100644 asset/static/libs/select2-4.0.3/js/select2.full.js create mode 100644 asset/static/libs/select2-4.0.3/js/select2.full.min.js create mode 100644 asset/static/libs/select2-4.0.3/js/select2.js create mode 100644 asset/static/libs/select2-4.0.3/js/select2.min.js create mode 100755 asset/static/stylesheets/common/custom.css create mode 100755 asset/static/stylesheets/common/modern.css create mode 100755 asset/static/stylesheets/common/modern.min.css create mode 100644 asset/static/views/widgets/modal.html create mode 100644 asset/template/layout/base.html create mode 100644 asset/template/views/base.html create mode 100644 asset/template/views/change_password.html create mode 100644 asset/template/views/error.html create mode 100644 asset/template/views/index.html create mode 100644 asset/template/views/login.html create mode 100755 bench.py create mode 100644 changer-dev.service create mode 100644 enums/user_type.go create mode 100644 http/iface/metric_count.go create mode 100644 http/iface/metric_duration.go create mode 100644 http/iface/rest.go create mode 100644 http/iface/rest_easyjson.go create mode 100644 http/init.go create mode 100644 http/middleware/logging/middleware.go create mode 100644 http/middleware/recovery/middleware.go create mode 100644 http/middleware/secure/middleware.go create mode 100644 http/middleware/session/data.go create mode 100644 http/middleware/session/middleware.go create mode 100644 http/middleware/session/role.go create mode 100644 http/profile.go create mode 100644 http/route/change_password.go create mode 100644 http/route/index.go create mode 100644 http/route/login.go create mode 100644 http/route/services.go create mode 100644 http/route/static.go create mode 100644 http/template/loader.go create mode 100644 http/template/renderer.go create mode 100644 main.go create mode 100644 settings.yml create mode 100644 util/config.go create mode 100644 util/crypt/aes.go create mode 100644 util/crypt/common.go create mode 100644 util/crypt/password.go create mode 100644 util/daemon.go create mode 100644 util/iface/bytes16.go create mode 100644 util/iface/bytes32.go create mode 100644 util/iface/bytes64.go create mode 100644 util/iface/serialize.go create mode 100644 util/iface/uuid.go create mode 100644 util/json.go create mode 100644 util/ldap/ldap.go create mode 100644 util/logger.go create mode 100644 util/parse.go create mode 100644 util/tool.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72dffb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ + +# Created by https://www.gitignore.io/api/intellij,go,linux,osx,windows + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +.idea +*.iml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + +### Go ### +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + + +### Linux ### +*~ +*.swp + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +build/ +bind/ +vendor/ +mecab/ +*.log +.vscode/ +changer + +settings_test.yml \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..90ac651 --- /dev/null +++ b/Makefile @@ -0,0 +1,61 @@ + + +# This how we want to name the binary output +BINARY=changer + +# These are the values we want to pass for VERSION and BUILD +# git tag 1.0.1 +# git commit -am "One more change after the tags" +VERSION=`git describe --always` +BUILD=`date +%FT%T%z` + +# Setup the -ldflags option for go build here, interpolate the variable values +LDFLAGS=-ldflags "-w -s -X amuz.es/gogs/infra/changer/util.version=${VERSION} -X amuz.es/gogs/infra/changer/util.buildDate=${BUILD}" +CGO_ENABLED=0 + + +# Builds the project +build: + go build ${LDFLAGS} -o ${BINARY} + strip -x ${BINARY} + +# Builds the project +setup: + go get -u github.com/kardianos/govendor + go get -u github.com/jteeuwen/go-bindata/... + # go get -u github.com/gogo/protobuf/proto + # go get -u github.com/gogo/protobuf/protoc-gen-gogo + # go get -u github.com/gogo/protobuf/gogoproto + # go get -u github.com/gogo/protobuf/protoc-gen-gofast + # go get -u github.com/gogo/protobuf/protoc-gen-gogofaster + # go get -u github.com/golang/protobuf/proto + ${GOPATH}/bin/govendor fetch -v +missing + #libjpeg-turbo +generate: + go get -u github.com/gogo/protobuf/proto + go get -u github.com/gogo/protobuf/protoc-gen-gogo + go get -u github.com/gogo/protobuf/gogoproto + go get -u github.com/gogo/protobuf/protoc-gen-gofast + go get -u github.com/gogo/protobuf/protoc-gen-gogofaster + go get -u github.com/golang/protobuf/proto + go get -u github.com/mailru/easyjson + protoc --gogofaster_out=. --proto_path=../../:. subsys/redis/app_token_data.proto + go-bindata -nomemcopy -ignore .DS_Store -prefix asset/static -o bind/static/data.go -pkg static asset/static/... + go-bindata -nomemcopy -ignore .DS_Store -prefix asset/template -o bind/template/data.go -pkg template asset/template/... + #${GOPATH}/bin/ffjson subsys/http/iface/rest.go + ${GOPATH}/bin/easyjson subsys/http/iface/rest.go +# go-bindata -debug -nomemcopy -ignore .DS_Store -prefix asset/static -o bind/static/data.go -pkg static asset/static/... +# go-bindata -debug -nomemcopy -ignore .DS_Store -prefix asset/template -o bind/template/data.go -pkg template asset/template/... + + +strip: + upx rooibos +# Installs our project: copies binaries +install: + go install ${LDFLAGS} + +# Cleans our project: deletes binaries +clean: + if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi + +.PHONY: clean install diff --git a/README.md b/README.md new file mode 100644 index 0000000..eec5db2 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +![alt tag](https://upload.wikimedia.org/wikipedia/commons/2/23/Golang.png) + +[![Build Status](https://travis-ci.org/Massad/gin-boilerplate.svg?branch=master)](https://travis-ci.org/Massad/gin-boilerplate) +[![Join the chat at https://gitter.im/Massad/gin-boilerplate](https://badges.gitter.im/Massad/gin-boilerplate.svg)](https://gitter.im/Massad/gin-boilerplate?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Welcome to **Golang Gin boilerplate**! + +The fastest way to deploy a restful api's with [Gin Framework](https://gin-gonic.github.io/gin/) with a structured project that defaults to **PostgreSQL** database and **Redis** as the session storage. + +## Configured with + +* [go-gorp](github.com/go-gorp/gorp): Go Relational Persistence +* [RedisStore](https://github.com/gin-gonic/contrib/tree/master/sessions): Gin middleware for session management with multi-backend support (currently cookie, Redis). +* Built-in **CORS Middleware** +* Feature **PostgreSQL 9.4** JSON queries +* Unit test + +### Installation + +``` +$ go get github.com/Massad/gin-boilerplate +``` + +``` +$ cd $GOPATH/src/github.com/Massad/gin-boilerplate +``` + +``` +$ go get -t -v ./... +``` + +> Sometimes you need to get this package manually +``` +$ go get github.com/bmizerany/assert +``` + +You will find the **database.sql** in `db/database.sql` + +And you can import the postgres database using this command: +``` +$ psql -U postgres -h localhost < ./db/database.sql +``` + +## Running Your Application + +``` +$ go run *.go +``` + +## Building Your Application + +``` +$ go build -v +``` + +``` +$ ./gin-boilerplate +``` + +## Testing Your Application + +``` +$ go test -v ./tests/* +``` + + +## Import Postman Collection (API's) +You can import from this [link](https://www.getpostman.com/collections/ac0680f90961bafd5de7). If you don't have **Postman**, check this link [https://www.getpostman.com](https://www.getpostman.com/) + +## Contribution + +You are welcome to contribute to keep it up to date and always improving! + +If you have any question or need help, drop a message at [https://gitter.im/Massad/gin-boilerplate](https://gitter.im/Massad/gin-boilerplate) + +--- + +## License +(The MIT License) + +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: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +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. diff --git a/asset/static/images/ajax-loader.gif b/asset/static/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29 GIT binary patch literal 3208 zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC; z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>* z2CROCDAbu#D`)S|J_o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5 zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT*EZWzJ zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#P|%fkvgUj~HfIp3CuXqCtYGtJ#me+n+-LmP( z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{ zpt8rzY$aw?W?=Ustv{jo?Ow@ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^ zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7 z_REZy&hMT^ySJB3W7l$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^ zTEe99ig2$5_qFr!$;7A6CJ}PJmRhli>w?LC}Y`#HLGy6 zMU4EhL~dKCN5Ut;U2jd*83ShBNiu zcJB0l9>1Modc?-oM<R4?}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8 zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RXvDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5| zR?GRdU}d6+Q`+JRW)|=v7$)XNkn3yE`!nAiSCvOB1jKT zG<1aK3s<0b0m==egTD#8i(Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^yx>}+a!ECd>#MMwddow z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{rwsgqtIU3<910$CJi)s?? z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M Bt + + + + \ No newline at end of file diff --git a/asset/static/images/ajax-loader.webp b/asset/static/images/ajax-loader.webp new file mode 100644 index 0000000000000000000000000000000000000000..05fee94250405bb60b1f773f3239d8b7360c0efe GIT binary patch literal 5456 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 Z8owOg_S*k}3N`?9y;9UrsCa1__)| literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.144.png b/asset/static/images/favicon.144.png new file mode 100644 index 0000000000000000000000000000000000000000..c492748f53c033917d1356d48ee5d5433effb986 GIT binary patch literal 16766 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%0AOwHw)3fn0?b+j{da z*g4W!QLcKnermp1ctT#B>$Jm;Tb%ap!_KeV?B>|z0H4>y-RKYRuj~N z@2NvX{YvUP>TtmSMexj3_KmCgTUQHVGZzc+1aWh639xbUvT+M&a`6lE@(A+@v2qFt sb8?bD{{{wV40R3wx}8l+3QTe?fSrCYk+@c;6@yr;sg zIWy;;GqY#ywbu5FijvGLR3cOe1oBEwR#FW-Ccpe3BZA-1E^-R+0BN-OpXgDuFFpwW7EaOCUh zqapR@O8t6erMa5z8$2?K9(jnQE;S4~jG244IXnRmg6c;s!);d*QYh&X)EA+Tum>BD zlyDZ?40|5EnI0Tr7W^&5Hr-{?d)2$7O=Oak=yfcH?jvoCh@ZIjaP@4!% z*F4|Et3evJ8=8m&H#Y?1#uF%pIQgRC^5P*XP5!hP;cyUKh)2afiK)V#%R4cKQ0Ad1 z?jqQ4gV0on=#i&VEHx}Sa)$FMW1I_jy^t&7;HBFXp@8F!;Clit9v{>>G3)Gq4{WH>L!XY;F;;R=_YRV zR58aSQp+(6If>{d?hIA=)H4qmS1})$>t@gn{iD=P++<>8TyttHw|XB-EgS2?ls7HQ zP!?}~i%~FzqKbPNOWh+ETk|n->%5AY4Oi-W95sUht`ztNTnu?U^8bY~57iG=wdf~q z;lxt6(#TDEBn{;yQZuL~ZWWm6j>egLrcld046(JN%f;ReRQaURM^GF;b(`z1Fbw^} zkc;gSYEC5Z#bL<9i&v|rmUAXFO{11W1Z_Eb`?(E%u%cvFqnskdt6_Oyx^FzeL56)F8X@cuT}UE(?^PU=p%}}) zn*fIBs{m~n4J`2oLes4fER+D!4hl#g)U*K7-~Rk~(g{_E`%E1|zhpNL(}J{y8xWDd zOBKQ%-Yu3OpZBVR1~PmPJ>I`jJT&G>9iduv2*K)w;&@~b@JCZY$mL#-L32?uJlSC zEEyR!z|TBQ%~Hed@uHY#`8vaftWr-O$w7}Bfe0($kSBV`Zy?z28Dcrs)2V)pT@KT+ z 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 literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.16.png b/asset/static/images/favicon.16.png new file mode 100644 index 0000000000000000000000000000000000000000..b0ddea61d00dc5d3b6bee9a2302a1e3c5f72c345 GIT binary patch literal 1542 zcmZ9Md0bRg6vxjD$_O+vEF+tVz%au$@Yn@0h1ez;WSIm?Q)I6UgTaD85j2t#Bq0>g zV8DPcRhxNCtP?oLYMcs%B11gnFIj#nB@CeMezG$k@lO;jK!D&9#n4ypJyQ658d zXCqPIejprS9(T zN~Kbx(EuJB8*_4U0szd>(Gj+@v$L(OZB$egU}RyyfC~{J0KiZjDXT)S zLgWn|25)I;>Ehx7(Z|mnm`sKUH(`?Um$`8O05dwe(0>;jA`yy8?U&*wbpY8Sm9wI^j zfPq)3RBmqEUO37WM=o#Rdzfnm21JA~fMsT8y1Kez7tkBrT@C7%bL({dNplk}M1%kU z1FWZ~#}$`5!aLdBe6V*-&FSE_fzCKz3FIr$=X!H;X1tb(NG?ti{nwd)%Sy)z~@NF?mx;YFc_mCS^VS%(I)H%ii*QPOdg@>kBVZe!)wHMccL)?gHmQ&G9MYR~KYs%ze$+WiOW>KhIodb6=f*W7aWEoyCRfBT&yM>~$ad;G-7_fEY} zou|9HKj`T_bGEPl-1!RwgY@CWp^rYkbb0v7C!c`v;aUtIaW~h%O$%mvhvHC2CWXwP}GVIca#17vt%#WPFrf z{u)oeKp*cw-vC!8Adq3K^8dd0pM=fXsafgy|4Z-&>dhx~AFVS-0;$5HLpwq?mi!B_ CSyy`i literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.24.png b/asset/static/images/favicon.24.png new file mode 100644 index 0000000000000000000000000000000000000000..2291624ced2a6c066a3a6078bd5115051d3351ef GIT binary patch literal 1683 zcmZ9MX;c&D5{5tatpZUNwP6cuK_HNTB!Z$1h6pHdlUM{~)1)aFgs=vIXi-*a0|WM1(d8YbjDRqJV&GVJB9F5RpI&NW;0m?mcs6-ZSsabLQV#O6yF#%cfN1$tS%|0?_z_+IEP7v^NZM_w@pRZUz7&4S;{77UL}dv2Xz1 z1p|OC20-^}8P~^II#3Mtz+%AeUi{Q{KVRyoTy^)O0ibqZFJ(YU+1@>+7@U`z(yaWK zn&xuO?f5tV6mH-!C-LsR<;2Ku%gNfiPqaW?jt%+>z7U$Rg@1 zt-0E{SF=lsx!SewmBihHx08QVKU4Ds)2=uoPv=Sa7!=<)rj$K?hfVqBKRgdMCC~9_ zAN^O84MDposbBo{=b08vk6ed_ZL3IBHl0{Gov6+_1Q;2QpfFhgVH^f_jPHOSP;ds^rJ={9UK%OW0y#Qq!CkCsp?JHGTN1X&ZO_U3#Ft&hnbXb;zxnp zr(_|$Ag5fFLvCd3Crlkfp)#Fv4J_`QF^}dQxbSnj-% znYnotJ1Nsb#mF;F(-5W!dBmy;u(?}RC9|`$a{z;Uz)rg0Kha{=I9bJ>f_;3#YTlht zq3AO26Pk}@F6NGmwA8V==^2U|dT3;0Sa0s41Zx6|m-(%Wk0X=K%V-n%CN6`Gbz&ip zKJs#RZgsJt=H0KZf2Mp$I7mgTb;hT@j{SJ9gXb5&*kEw&gnX(u#wIr>$CaSRpzmj% z25#UP|IIds^!l=YiMsxKr?}aJMxxmyP+4i`It?0_}cL2j`IYvXm>4A?LcY*O;Px=GKl!f9roBJcV2_b z<26@Tn*|)Qe662I+d6*|y^1qN3p>sNUtH>r%87gMl!X~Vc8BQAIPx5(Z>)*jMx%bO zw91NbOtSJC8ey?ml}PH0AHoDv8ONy^9)DNALHeyBN-q8-pFer%)Mk|O>@7B$v~*J- z5VSbu1`&tbE#_~P_da!aie27+T)RIktRSkJJ+9j;ex971Tw09k26JMuSRXO5Qa-)Q zpIsUCs-rvXm;3I@ZTV{A&Ysb>w)G++>3C&_L8q3SdueIubaekR^}?uRJWRu-?1uNn zK*q3j=x_}&WECiXFrg=-XDeUy80z}VN_>%`zm4_Cc zTbOg4-#-+)`52pIJTI6@b4 zg@tuN+&thl2UI1wAr?kU;QGYB!gI}{Evpef^`>w zTPuP`HJM$7y1>5a)9#q1tWMyUau4jAYFVfw^|nL6_ekyn9qa~VF9gX3J#(=#AnrYQ z(-^mJVlIWmTti9$;J aKL8W^qeB)o|>;Ve^ literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.32.png b/asset/static/images/favicon.32.png new file mode 100644 index 0000000000000000000000000000000000000000..dca2cc6fe25fa32b977ee7599797a30f284a6273 GIT binary patch literal 2423 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 G=>Gvl-^2<4 literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.64.png b/asset/static/images/favicon.64.png new file mode 100644 index 0000000000000000000000000000000000000000..a75f0e3757d8c8f4678ade1688d8c889d92f3b0f GIT binary patch literal 5931 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 HEhGL16gf^^ literal 0 HcmV?d00001 diff --git a/asset/static/images/favicon.ico b/asset/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..008d96583c8a86d82ac336cfbf13994b6ba781ea GIT binary patch literal 34494 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 content.height()) { + content.attr('style', 'min-height:' + height + 'px !important'); + } + }; + + + domReady(function () { + sidebarAndContentHeight(); + $(window).on('resize', sidebarAndContentHeight); + window.$buoop = {vs: {i: 9, f: -2, o: -2, s: 6, c: -2}, unsecure: true, api: 4}; + require(['browser-update']); + }); +}); \ No newline at end of file diff --git a/asset/static/javascripts/common/mixed.js b/asset/static/javascripts/common/mixed.js new file mode 100644 index 0000000..4071da3 --- /dev/null +++ b/asset/static/javascripts/common/mixed.js @@ -0,0 +1,26 @@ +define('javascripts/common/tether.mixed',['tether'], function (tether) { + "use strict"; + window.Tether=tether; + return tether; +}); +define('javascripts/common/toastr.mixed',['toastr'], function (toastr) { + "use strict"; + toastr.options = { + closeButton: true, + debug: false, + newestOnTop: true, + progressBar: false, + positionClass: 'toast-top-right', + preventDuplicates: false, + onclick: null, + showDuration: '300', + hideDuration: '1000', + timeOut: '5000', + extendedTimeOut: '1000', + showEasing: 'swing', + hideEasing: 'linear', + showMethod: 'fadeIn', + hideMethod: 'fadeOut' + }; + return toastr; +}); \ No newline at end of file diff --git a/asset/static/javascripts/widgets/modal.js b/asset/static/javascripts/widgets/modal.js new file mode 100644 index 0000000..8c1e1d7 --- /dev/null +++ b/asset/static/javascripts/widgets/modal.js @@ -0,0 +1,20 @@ +define(['jquery', 'underscore', 'backbone.bootstrapModal', 'tpl!views/widgets/modal'], function ($, _, Modal, template) { + "use strict"; + return Modal.extend({ + initialize: function (options) { + this.options = _.extend({ + title: null, + okText: 'OK', + focusOk: true, + okCloses: false, + cancelText: 'Cancel', + showFooter: true, + allowCancel: true, + escape: true, + animate: true, + template: template, + enterTriggersOk: false + }, options); + } + }); +}); \ No newline at end of file diff --git a/asset/static/libs/backbone-bootstrap-modal/backbone-bootstrap-modal.js b/asset/static/libs/backbone-bootstrap-modal/backbone-bootstrap-modal.js new file mode 100755 index 0000000..0815e2e --- /dev/null +++ b/asset/static/libs/backbone-bootstrap-modal/backbone-bootstrap-modal.js @@ -0,0 +1,284 @@ +/** + * Bootstrap Modal wrapper for use with Backbone. + * + * Takes care of instantiation, manages multiple modals, + * adds several options and removes the element from the DOM when closed + * + * @author Charles Davison + * + * Events: + * shown: Fired when the modal has finished animating in + * hidden: Fired when the modal has finished animating out + * cancel: The user dismissed the modal + * ok: The user clicked OK + */ +define(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) { + + //Set custom template settings + var _interpolateBackup = _.templateSettings; + _.templateSettings = { + interpolate: /\{\{(.+?)\}\}/g, + evaluate: /<%([\s\S]+?)%>/g + }; + + var template = _.template('\ +

\ + '); + + //Reset to users' template settings + _.templateSettings = _interpolateBackup; + + + var Modal = Backbone.View.extend({ + + className: 'modal', + + events: { + 'click .close': function(event) { + event.preventDefault(); + + this.trigger('cancel'); + + if (this.options.content && this.options.content.trigger) { + this.options.content.trigger('cancel', this); + } + }, + 'click .cancel': function(event) { + event.preventDefault(); + + this.trigger('cancel'); + + if (this.options.content && this.options.content.trigger) { + this.options.content.trigger('cancel', this); + } + }, + 'click .ok': function(event) { + event.preventDefault(); + + this.trigger('ok'); + + if (this.options.content && this.options.content.trigger) { + this.options.content.trigger('ok', this); + } + + if (this.options.okCloses) { + this.close(); + } + }, + 'keypress': function(event) { + if (this.options.enterTriggersOk && event.which == 13) { + event.preventDefault(); + + this.trigger('ok'); + + if (this.options.content && this.options.content.trigger) { + this.options.content.trigger('ok', this); + } + + if (this.options.okCloses) { + this.close(); + } + } + } + }, + + /** + * Creates an instance of a Bootstrap Modal + * + * @see http://twitter.github.com/bootstrap/javascript.html#modals + * + * @param {Object} options + * @param {String|View} [options.content] Modal content. Default: none + * @param {String} [options.title] Title. Default: none + * @param {String} [options.okText] Text for the OK button. Default: 'OK' + * @param {String} [options.cancelText] Text for the cancel button. Default: 'Cancel'. If passed a falsey value, the button will be removed + * @param {Boolean} [options.allowCancel Whether the modal can be closed, other than by pressing OK. Default: true + * @param {Boolean} [options.escape] Whether the 'esc' key can dismiss the modal. Default: true, but false if options.cancellable is true + * @param {Boolean} [options.animate] Whether to animate in/out. Default: false + * @param {Function} [options.template] Compiled underscore template to override the default one + * @param {Boolean} [options.enterTriggersOk] Whether the 'enter' key will trigger OK. Default: false + */ + initialize: function(options) { + this.options = _.extend({ + title: null, + okText: 'OK', + focusOk: true, + okCloses: true, + cancelText: 'Cancel', + showFooter: true, + allowCancel: true, + escape: true, + animate: false, + template: template, + enterTriggersOk: false + }, options); + }, + + /** + * Creates the DOM element + * + * @api private + */ + render: function() { + var $el = this.$el, + options = this.options, + content = options.content; + + //Create the modal container + $el.html(options.template(options)); + + var $content = this.$content = $el.find('.modal-body') + + //Insert the main content if it's a view + if (content && content.$el) { + content.render(); + $el.find('.modal-body').html(content.$el); + } + + if (options.animate) $el.addClass('fade'); + + this.isRendered = true; + + return this; + }, + + /** + * Renders and shows the modal + * + * @param {Function} [cb] Optional callback that runs only when OK is pressed. + */ + open: function(cb) { + if (!this.isRendered) this.render(); + + var self = this, + $el = this.$el; + + //Create it + $el.modal(_.extend({ + keyboard: this.options.allowCancel, + backdrop: this.options.allowCancel ? true : 'static' + }, this.options.modalOptions)); + + //Focus OK button + $el.one('shown.bs.modal', function() { + if (self.options.focusOk) { + $el.find('.btn.ok').focus(); + } + + if (self.options.content && self.options.content.trigger) { + self.options.content.trigger('shown', self); + } + + self.trigger('shown'); + }); + + //Adjust the modal and backdrop z-index; for dealing with multiple modals + var numModals = Modal.count, + $backdrop = $('.modal-backdrop:eq('+numModals+')'), + backdropIndex = parseInt($backdrop.css('z-index'),10), + elIndex = parseInt($backdrop.css('z-index'), 10); + + $backdrop.css('z-index', backdropIndex + numModals); + this.$el.css('z-index', elIndex + numModals); + + if (this.options.allowCancel) { + $backdrop.one('click', function() { + if (self.options.content && self.options.content.trigger) { + self.options.content.trigger('cancel', self); + } + + self.trigger('cancel'); + }); + + $(document).one('keyup.dismiss.modal', function (e) { + e.which == 27 && self.trigger('cancel'); + + if (self.options.content && self.options.content.trigger) { + e.which == 27 && self.options.content.trigger('shown', self); + } + }); + } + + this.on('cancel', function() { + self.close(); + }); + + Modal.count++; + + //Run callback on OK if provided + if (cb) { + self.on('ok', cb); + } + + return this; + }, + + /** + * Closes the modal + */ + close: function() { + var self = this, + $el = this.$el; + + //Check if the modal should stay open + if (this._preventClose) { + this._preventClose = false; + return; + } + + $el.one('hidden.bs.modal', function onHidden(e) { + // Ignore events propagated from interior objects, like bootstrap tooltips + if(e.target !== e.currentTarget){ + return $el.one('hidden', onHidden); + } + self.remove(); + + if (self.options.content && self.options.content.trigger) { + self.options.content.trigger('hidden', self); + } + + self.trigger('hidden'); + }); + + $el.modal('hide'); + + Modal.count--; + }, + + /** + * Stop the modal from closing. + * Can be called from within a 'close' or 'ok' event listener. + */ + preventClose: function() { + this._preventClose = true; + } + }, { + //STATICS + + //The number of modals on display + count: 0 + }); + + return Modal; + +}); diff --git a/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.js b/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.js new file mode 100644 index 0000000..b58e493 --- /dev/null +++ b/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.js @@ -0,0 +1,136 @@ +// Backbone.ComputedFields, v0.0.10 +// Copyright (c)2014 alexander.beletsky@gmail.com +// Distributed under MIT license +// https://github.com/alexanderbeletsky/backbone-computedfields + +Backbone.ComputedFields = (function(Backbone, _){ + + var ComputedFields = function (model) { + this.model = model; + this._computedFields = []; + + this.initialize(); + }; + + _.extend(ComputedFields.prototype, { + initialize: function () { + _.bindAll( + this, + '_bindModelEvents', + '_computeFieldValue', + '_dependentFields', + '_isModelInitialized', + '_lookUpComputedFields', + '_thenComputedChanges', + '_thenDependentChanges', + '_toJSON', + '_wrapJSON', + 'initialize' + ); + + this._lookUpComputedFields(); + this._bindModelEvents(); + this._wrapJSON(); + }, + + _lookUpComputedFields: function () { + for (var obj in this.model.computed) { + var field = this.model.computed[obj]; + + if (field && (field.set || field.get)) { + this._computedFields.push({name: obj, field: field}); + } + } + }, + + _bindModelEvents: function () { + _.each(this._computedFields, function (computedField) { + var fieldName = computedField.name; + var field = computedField.field; + + var updateComputed = _.bind(function () { + var value = this._computeFieldValue(field); + this.model.set(fieldName, value, { skipChangeEvent: true }); + }, this); + + var updateDependent = _.bind(function (model, value, options) { + if (options && options.skipChangeEvent) { + return; + } + + if (field.set) { + var fields = this._dependentFields(field.depends); + value = value || this.model.get(fieldName); + + field.set.call(this.model, value, fields); + this.model.set(fields, options); + } + }, this); + + this._thenDependentChanges(field.depends, updateComputed); + this._thenComputedChanges(fieldName, updateDependent); + + if (this._isModelInitialized()) { + updateComputed(); + } + }, this); + }, + + _isModelInitialized: function () { + return !_.isEmpty(this.model.attributes); + }, + + _thenDependentChanges: function (depends, callback) { + _.each(depends, function (name) { + if (typeof (name) === 'string') { + this.model.on('change:' + name, callback); + } + + if (typeof (name) === 'function') { + name.call(this.model, callback); + } + }, this); + }, + + _thenComputedChanges: function (fieldName, callback) { + this.model.on('change:' + fieldName, callback); + }, + + _wrapJSON: function () { + this.model.toJSON = _.wrap(this.model.toJSON, this._toJSON); + }, + + _toJSON: function (toJSON) { + var args = Array.prototype.slice.call(arguments, 1), + attributes = toJSON.apply(this.model, args), + strip = !!(args[0] || {}).computedFields; + + var stripped = strip ? {} : _.reduce(this._computedFields, function (memo, computed) { + if (computed.field.toJSON === false) { + memo.push(computed.name); + } + return memo; + },[]); + + return _.omit(attributes, stripped); + }, + + _computeFieldValue: function (computedField) { + if (computedField && computedField.get) { + var fields = this._dependentFields(computedField.depends); + return computedField.get.call(this.model, fields); + } + }, + + _dependentFields: function (depends) { + return _.reduce(depends, function (memo, field) { + memo[field] = this.model.get(field); + return memo; + }, {}, this); + } + + }); + + return ComputedFields; + +})(Backbone, _); \ No newline at end of file diff --git a/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.min.js b/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.min.js new file mode 100644 index 0000000..0db4dae --- /dev/null +++ b/asset/static/libs/backbone-computedfields-0.0.11/backbone.computedfields.min.js @@ -0,0 +1 @@ +Backbone.ComputedFields=function(a,b){var c=function(a){this.model=a,this._computedFields=[],this.initialize()};return b.extend(c.prototype,{initialize:function(){b.bindAll(this,"_bindModelEvents","_computeFieldValue","_dependentFields","_isModelInitialized","_lookUpComputedFields","_thenComputedChanges","_thenDependentChanges","_toJSON","_wrapJSON","initialize"),this._lookUpComputedFields(),this._bindModelEvents(),this._wrapJSON()},_lookUpComputedFields:function(){for(var a in this.model.computed){var b=this.model.computed[a];b&&(b.set||b.get)&&this._computedFields.push({name:a,field:b})}},_bindModelEvents:function(){b.each(this._computedFields,function(a){var c=a.name,d=a.field,e=b.bind(function(){var a=this._computeFieldValue(d);this.model.set(c,a,{skipChangeEvent:!0})},this),f=b.bind(function(a,b,e){if((!e||!e.skipChangeEvent)&&d.set){var f=this._dependentFields(d.depends);b=b||this.model.get(c),d.set.call(this.model,b,f),this.model.set(f,e)}},this);this._thenDependentChanges(d.depends,e),this._thenComputedChanges(c,f),this._isModelInitialized()&&e()},this)},_isModelInitialized:function(){return!b.isEmpty(this.model.attributes)},_thenDependentChanges:function(a,c){b.each(a,function(a){"string"==typeof a&&this.model.on("change:"+a,c),"function"==typeof a&&a.call(this.model,c)},this)},_thenComputedChanges:function(a,b){this.model.on("change:"+a,b)},_wrapJSON:function(){this.model.toJSON=b.wrap(this.model.toJSON,this._toJSON)},_toJSON:function(a){var c=Array.prototype.slice.call(arguments,1),d=a.apply(this.model,c),e=!!(c[0]||{}).computedFields,f=e?{}:b.reduce(this._computedFields,function(a,b){return b.field.toJSON===!1&&a.push(b.name),a},[]);return b.omit(d,f)},_computeFieldValue:function(a){if(a&&a.get){var b=this._dependentFields(a.depends);return a.get.call(this.model,b)}},_dependentFields:function(a){return b.reduce(a,function(a,b){return a[b]=this.model.get(b),a},{},this)}}),c}(Backbone,_); \ No newline at end of file diff --git a/asset/static/libs/requirejs-svg-0.0.1/svg.js b/asset/static/libs/requirejs-svg-0.0.1/svg.js new file mode 100644 index 0000000..523320f --- /dev/null +++ b/asset/static/libs/requirejs-svg-0.0.1/svg.js @@ -0,0 +1,75 @@ +/*jslint regexp: true */ +/*global define */ + +define(['module', 'text'], function (module, textPlugin) { + 'use strict'; + + var svg = { + buildMap: {}, + sprite_id: 'requirejs-svg-sprite', + sprite: null, + + extractGraphicAsSymbol: function(document, svgText) { + var div = document.createElement('div'); + div.innerHTML = svgText; + var element = div.querySelector('svg'); + var id = element.getAttribute('id'); + var viewBox = element.getAttribute('viewbox') || element.getAttribute('viewBox'); + return svg.createSymbol(document, id, element, viewBox); + }, + + createSymbol: function(document, id, element, viewBox) { + var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol'); + while (element.firstChild) { + symbol.appendChild(element.firstChild); + } + typeof id === 'string' && symbol.setAttribute('id', id); + typeof viewBox === 'string' && symbol.setAttribute('viewBox', viewBox); + return symbol; + }, + + createSprite: function(document) { + svg.sprite = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.sprite.setAttribute('style', 'display: none'); + svg.sprite.setAttribute('id', this.sprite_id); + return svg.sprite; + }, + + appendSprite: function(content) { + if (! svg.sprite) { + svg.createSprite(document); + document.body.appendChild(svg.sprite); + } + + svg.sprite.appendChild( svg.extractGraphicAsSymbol(document, content) ); + }, + + finishLoad: function(name, onLoad, config) { + return function(content) { + if (config && !config.isBuild) { + svg.appendSprite(content); + } + else { + svg.buildMap[name] = content; + } + + return onLoad(content); + }; + }, + + load: function(name, req, onLoad, config) { + textPlugin.load(name + '!strip', req, svg.finishLoad(name, onLoad, config), config); + }, + + write: function (pluginName, moduleName, write/*, config*/) { + if (svg.buildMap.hasOwnProperty(moduleName)) { + var content = textPlugin.jsEscape(svg.buildMap[moduleName]); + write.asModule(pluginName + "!" + moduleName, + "define(['" + pluginName + "'], function (svg) { svg.appendSprite('" + content + "');});\n" + ); + } + } + }; + + return svg; +}); diff --git a/asset/static/libs/requirejs-svg-0.0.1/svg.min.js b/asset/static/libs/requirejs-svg-0.0.1/svg.min.js new file mode 100644 index 0000000..4ff4aa5 --- /dev/null +++ b/asset/static/libs/requirejs-svg-0.0.1/svg.min.js @@ -0,0 +1,3 @@ +define(["module","text"],function(g,f){var b={b:{},j:"requirejs-svg-sprite",a:null,h:function(a,e){var c=a.createElement("div");c.innerHTML=e;var c=c.querySelector("svg"),d=c.getAttribute("id"),f=c.getAttribute("viewbox")||c.getAttribute("viewBox");return b.g(a,d,c,f)},g:function(a,b,c,d){for(a=a.createElementNS("http://www.w3.org/2000/svg","symbol");c.firstChild;)a.appendChild(c.firstChild);"string"===typeof b&&a.setAttribute("id",b);"string"===typeof d&&a.setAttribute("viewBox",d);return a},f:function(a){b.a= + a.createElementNS("http://www.w3.org/2000/svg","svg");b.a.setAttribute("style","display: none");b.a.setAttribute("id",this.j);return b.a},c:function(a){b.a||(b.f(document),document.body.appendChild(b.a));b.a.appendChild(b.h(document,a))},i:function(a,e,c){return function(d){c&&!c.m?b.c(d):b.b[a]=d;return e(d)}},load:function(a,e,c,d){f.load(a+"!strip",e,b.i(a,c,d),d)},write:function(a,e,c){if(b.b.hasOwnProperty(e)){var d=f.o(b.b[e]);c.l(a+"!"+e,"define(['"+a+"'], function (svg) { svg.appendSprite('"+ + d+"');});\n")}}};return b}); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/css/select2.css b/asset/static/libs/select2-4.0.3/css/select2.css new file mode 100644 index 0000000..447b2b8 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/css/select2.css @@ -0,0 +1,484 @@ +.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; + height: 1px !important; + margin: -1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !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__placeholder { + color: #999; + margin-top: 5px; + float: left; } + .select2-container--default .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-top: 5px; + margin-right: 10px; } + .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-selection__placeholder, .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, white 50%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 50%, #eeeeee 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, #eeeeee 50%, #cccccc 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 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, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 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, #eeeeee 50%, white 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, white 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; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + 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: white; + 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: white; } + +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; } diff --git a/asset/static/libs/select2-4.0.3/css/select2.min.css b/asset/static/libs/select2-4.0.3/css/select2.min.css new file mode 100644 index 0000000..76de04d --- /dev/null +++ b/asset/static/libs/select2-4.0.3/css/select2.min.css @@ -0,0 +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;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !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__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.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-selection__placeholder,.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}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{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} diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ar.js b/asset/static/libs/select2-4.0.3/js/i18n/ar.js new file mode 100644 index 0000000..01a6882 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ar.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="الرجاء حذف "+t+" عناصر";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="الرجاء إضافة "+t+" عناصر";return n},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(e){var t="تستطيع إختيار "+e.maximum+" بنود فقط";return t},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/az.js b/asset/static/libs/select2-4.0.3/js/i18n/az.js new file mode 100644 index 0000000..2accb97 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/az.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/az",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return t+" simvol silin"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(e){return"Sadəcə "+e.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/bg.js b/asset/static/libs/select2-4.0.3/js/i18n/bg.js new file mode 100644 index 0000000..35ae989 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/bg.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/bg",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Моля въведете с "+t+" по-малко символ";return t>1&&(n+="a"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Моля въведете още "+t+" символ";return t>1&&(n+="a"),n},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(e){var t="Можете да направите до "+e.maximum+" ";return e.maximum>1?t+="избора":t+="избор",t},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ca.js b/asset/static/libs/select2-4.0.3/js/i18n/ca.js new file mode 100644 index 0000000..fdb5f3d --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ca.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Si us plau, elimina "+t+" car";return t==1?n+="àcter":n+="àcters",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Si us plau, introdueix "+t+" car";return t==1?n+="àcter":n+="àcters",n},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var t="Només es pot seleccionar "+e.maximum+" element";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/cs.js b/asset/static/libs/select2-4.0.3/js/i18n/cs.js new file mode 100644 index 0000000..9651378 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/cs.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/cs",[],function(){function e(e,t){switch(e){case 2:return t?"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(t){var n=t.input.length-t.maximum;return n==1?"Prosím zadejte o jeden znak méně":n<=4?"Prosím zadejte o "+e(n,!0)+" znaky méně":"Prosím zadejte o "+n+" znaků méně"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím zadejte ještě jeden znak":n<=4?"Prosím zadejte ještě další "+e(n,!0)+" znaky":"Prosím zadejte ještě dalších "+n+" znaků"},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(t){var n=t.maximum;return n==1?"Můžete zvolit jen jednu položku":n<=4?"Můžete zvolit maximálně "+e(n,!1)+" položky":"Můžete zvolit maximálně "+n+" položek"},noResults:function(){return"Nenalezeny žádné položky"},searching:function(){return"Vyhledávání…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/da.js b/asset/static/libs/select2-4.0.3/js/i18n/da.js new file mode 100644 index 0000000..501c51e --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/da.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Angiv venligst "+t+" tegn mindre";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Angiv venligst "+t+" tegn mere";return n},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var t="Du kan kun vælge "+e.maximum+" emne";return e.maximum!=1&&(t+="r"),t},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/de.js b/asset/static/libs/select2-4.0.3/js/i18n/de.js new file mode 100644 index 0000000..9a6d553 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/de.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/de",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var t="Sie können nur "+e.maximum+" Eintr";return e.maximum===1?t+="ag":t+="äge",t+=" auswählen",t},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/el.js b/asset/static/libs/select2-4.0.3/js/i18n/el.js new file mode 100644 index 0000000..4735d14 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/el.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Παρακαλώ διαγράψτε "+t+" χαρακτήρ";return t==1&&(n+="α"),t!=1&&(n+="ες"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Παρακαλώ συμπληρώστε "+t+" ή περισσότερους χαρακτήρες";return n},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(e){var t="Μπορείτε να επιλέξετε μόνο "+e.maximum+" επιλογ";return e.maximum==1&&(t+="ή"),e.maximum!=1&&(t+="ές"),t},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/en.js b/asset/static/libs/select2-4.0.3/js/i18n/en.js new file mode 100644 index 0000000..8e80ede --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/en.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Please delete "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Please enter "+t+" or more characters";return n},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/es.js b/asset/static/libs/select2-4.0.3/js/i18n/es.js new file mode 100644 index 0000000..0a09650 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/es.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"La carga falló"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor, elimine "+t+" car";return t==1?n+="ácter":n+="acteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Por favor, introduzca "+t+" car";return t==1?n+="ácter":n+="acteres",n},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var t="Sólo puede seleccionar "+e.maximum+" elemento";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/et.js b/asset/static/libs/select2-4.0.3/js/i18n/et.js new file mode 100644 index 0000000..c70f4a5 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/et.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" vähem",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" rohkem",n},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var t="Saad vaid "+e.maximum+" tulemus";return e.maximum==1?t+="e":t+="t",t+=" valida",t},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/eu.js b/asset/static/libs/select2-4.0.3/js/i18n/eu.js new file mode 100644 index 0000000..9336053 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/eu.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gutxiago",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gehiago",n},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return e.maximum===1?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/fa.js b/asset/static/libs/select2-4.0.3/js/i18n/fa.js new file mode 100644 index 0000000..5118cd2 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/fa.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="لطفاً "+t+" کاراکتر را حذف نمایید";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لطفاً تعداد "+t+" کاراکتر یا بیشتر وارد نمایید";return n},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(e){var t="شما تنها می‌توانید "+e.maximum+" آیتم را انتخاب نمایید";return t},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/fi.js b/asset/static/libs/select2-4.0.3/js/i18n/fi.js new file mode 100644 index 0000000..9e60f26 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/fi.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Ole hyvä ja anna "+t+" merkkiä vähemmän"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Ole hyvä ja anna "+t+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(e){return"Voit valita ainoastaan "+e.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/fr.js b/asset/static/libs/select2-4.0.3/js/i18n/fr.js new file mode 100644 index 0000000..e4a6650 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/fr.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Supprimez "+t+" caractère";return t!==1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Saisissez "+t+" caractère";return t!==1&&(n+="s"),n},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){var t="Vous pouvez seulement sélectionner "+e.maximum+" élément";return e.maximum!==1&&(t+="s"),t},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/gl.js b/asset/static/libs/select2-4.0.3/js/i18n/gl.js new file mode 100644 index 0000000..02f258f --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/gl.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/gl",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Elimine ";return t===1?n+="un carácter":n+=t+" caracteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Engada ";return t===1?n+="un carácter":n+=t+" caracteres",n},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){var t="Só pode ";return e.maximum===1?t+="un elemento":t+=e.maximum+" elementos",t},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/he.js b/asset/static/libs/select2-4.0.3/js/i18n/he.js new file mode 100644 index 0000000..881f8d3 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/he.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="נא למחוק ";return t===1?n+="תו אחד":n+=t+" תווים",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="נא להכניס ";return t===1?n+="תו אחד":n+=t+" תווים",n+=" או יותר",n},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(e){var t="באפשרותך לבחור עד ";return e.maximum===1?t+="פריט אחד":t+=e.maximum+" פריטים",t},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/hi.js b/asset/static/libs/select2-4.0.3/js/i18n/hi.js new file mode 100644 index 0000000..e829684 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/hi.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" अक्षर को हटा दें";return t>1&&(n=t+" अक्षरों को हटा दें "),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="कृपया "+t+" या अधिक अक्षर दर्ज करें";return n},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(e){var t="आप केवल "+e.maximum+" आइटम का चयन कर सकते हैं";return t},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/hr.js b/asset/static/libs/select2-4.0.3/js/i18n/hr.js new file mode 100644 index 0000000..89f7b12 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/hr.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hr",[],function(){function e(e){var t=" "+e+" znak";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+="a"):t+="ova",t}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Unesite "+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return"Unesite još "+e(n)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(e){return"Maksimalan broj odabranih stavki je "+e.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/hu.js b/asset/static/libs/select2-4.0.3/js/i18n/hu.js new file mode 100644 index 0000000..74c8a90 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/hu.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Túl hosszú. "+t+" karakterrel több, mint kellene."},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Túl rövid. Még "+t+" 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…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/id.js b/asset/static/libs/select2-4.0.3/js/i18n/id.js new file mode 100644 index 0000000..9586782 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/id.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Hapuskan "+t+" huruf"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Masukkan "+t+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(e){return"Anda hanya dapat memilih "+e.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/is.js b/asset/static/libs/select2-4.0.3/js/i18n/is.js new file mode 100644 index 0000000..ab97a14 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/is.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/is",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vinsamlegast styttið texta um "+t+" staf";return t<=1?n:n+"i"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vinsamlegast skrifið "+t+" staf";return t>1&&(n+="i"),n+=" í viðbót",n},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(e){return"Þú getur aðeins valið "+e.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/it.js b/asset/static/libs/select2-4.0.3/js/i18n/it.js new file mode 100644 index 0000000..7796b9f --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/it.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Per favore cancella "+t+" caratter";return t!==1?n+="i":n+="e",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Per favore inserisci "+t+" o più caratteri";return n},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var t="Puoi selezionare solo "+e.maximum+" element";return e.maximum!==1?t+="i":t+="o",t},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ja.js b/asset/static/libs/select2-4.0.3/js/i18n/ja.js new file mode 100644 index 0000000..9f4fff6 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ja.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" 文字を削除してください";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="少なくとも "+t+" 文字を入力してください";return n},loadingMore:function(){return"読み込み中…"},maximumSelected:function(e){var t=e.maximum+" 件しか選択できません";return t},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/km.js b/asset/static/libs/select2-4.0.3/js/i18n/km.js new file mode 100644 index 0000000..8e94adc --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/km.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="សូមលុបចេញ "+t+" អក្សរ";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="សូមបញ្ចូល"+t+" អក្សរ រឺ ច្រើនជាងនេះ";return n},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(e){var t="អ្នកអាចជ្រើសរើសបានតែ "+e.maximum+" ជម្រើសប៉ុណ្ណោះ";return t},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ko.js b/asset/static/libs/select2-4.0.3/js/i18n/ko.js new file mode 100644 index 0000000..4ed0321 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ko.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/lt.js b/asset/static/libs/select2-4.0.3/js/i18n/lt.js new file mode 100644 index 0000000..05f3a6e --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/lt.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lt",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Pašalinkite "+n+" simbol";return r+=e(n,"į","ius","ių"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Įrašykite dar "+n+" simbol";return r+=e(n,"į","ius","ių"),r},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(t){var n="Jūs galite pasirinkti tik "+t.maximum+" element";return n+=e(t.maximum,"ą","us","ų"),n},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/lv.js b/asset/static/libs/select2-4.0.3/js/i18n/lv.js new file mode 100644 index 0000000..df8ee94 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/lv.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lv",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Lūdzu ievadiet par "+n;return r+=" simbol"+e(n,"iem","u","iem"),r+" mazāk"},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Lūdzu ievadiet vēl "+n;return r+=" simbol"+e(n,"us","u","us"),r},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(t){var n="Jūs varat izvēlēties ne vairāk kā "+t.maximum;return n+=" element"+e(t.maximum,"us","u","us"),n},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/mk.js b/asset/static/libs/select2-4.0.3/js/i18n/mk.js new file mode 100644 index 0000000..319ecca --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/mk.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/mk",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Ве молиме внесете "+e.maximum+" помалку карактер";return e.maximum!==1&&(n+="и"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Ве молиме внесете уште "+e.maximum+" карактер";return e.maximum!==1&&(n+="и"),n},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(e){var t="Можете да изберете само "+e.maximum+" ставк";return e.maximum===1?t+="а":t+="и",t},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ms.js b/asset/static/libs/select2-4.0.3/js/i18n/ms.js new file mode 100644 index 0000000..4258f12 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ms.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Sila hapuskan "+t+" aksara"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Sila masukkan "+t+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(e){return"Anda hanya boleh memilih "+e.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/nb.js b/asset/static/libs/select2-4.0.3/js/i18n/nb.js new file mode 100644 index 0000000..6770087 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/nb.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Vennligst fjern "+t+" tegn"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vennligst skriv inn ";return t>1?n+=" flere tegn":n+=" tegn til",n},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…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/nl.js b/asset/static/libs/select2-4.0.3/js/i18n/nl.js new file mode 100644 index 0000000..8bd5e3c --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/nl.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Gelieve "+t+" karakters te verwijderen";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Gelieve "+t+" of meer karakters in te voeren";return n},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var t=e.maximum==1?"kan":"kunnen",n="Er "+t+" maar "+e.maximum+" item";return e.maximum!=1&&(n+="s"),n+=" worden geselecteerd",n},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/pl.js b/asset/static/libs/select2-4.0.3/js/i18n/pl.js new file mode 100644 index 0000000..54ba28e --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/pl.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pl",[],function(){var e=["znak","znaki","znaków"],t=["element","elementy","elementów"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Usuń "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Podaj przynajmniej "+r+" "+n(r,e)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(e){return"Możesz zaznaczyć tylko "+e.maximum+" "+n(e.maximum,t)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/pt-BR.js b/asset/static/libs/select2-4.0.3/js/i18n/pt-BR.js new file mode 100644 index 0000000..a6629c8 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/pt-BR.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Apague "+t+" caracter";return t!=1&&(n+="es"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Digite "+t+" ou mais caracteres";return n},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var t="Você só pode selecionar "+e.maximum+" ite";return e.maximum==1?t+="m":t+="ns",t},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/pt.js b/asset/static/libs/select2-4.0.3/js/i18n/pt.js new file mode 100644 index 0000000..0cbda56 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/pt.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor apague "+t+" ";return n+=t!=1?"caracteres":"carácter",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Introduza "+t+" ou mais caracteres";return n},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var t="Apenas pode seleccionar "+e.maximum+" ";return t+=e.maximum!=1?"itens":"item",t},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ro.js b/asset/static/libs/select2-4.0.3/js/i18n/ro.js new file mode 100644 index 0000000..788a263 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ro.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return 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 t!==1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vă rugăm să introduceți "+t+"sau mai multe caractere";return n},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",e.maximum!==1&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/ru.js b/asset/static/libs/select2-4.0.3/js/i18n/ru.js new file mode 100644 index 0000000..9ecab80 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/ru.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ru",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Пожалуйста, введите на "+n+" символ";return r+=e(n,"","a","ов"),r+=" меньше",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Пожалуйста, введите еще хотя бы "+n+" символ";return r+=e(n,"","a","ов"),r},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(t){var n="Вы можете выбрать не более "+t.maximum+" элемент";return n+=e(t.maximum,"","a","ов"),n},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/sk.js b/asset/static/libs/select2-4.0.3/js/i18n/sk.js new file mode 100644 index 0000000..82f2941 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/sk.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadajte o jeden znak menej":n>=2&&n<=4?"Prosím, zadajte o "+e[n](!0)+" znaky menej":"Prosím, zadajte o "+n+" znakov menej"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadajte ešte jeden znak":n<=4?"Prosím, zadajte ešte ďalšie "+e[n](!0)+" znaky":"Prosím, zadajte ešte ďalších "+n+" znakov"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(t){return t.maximum==1?"Môžete zvoliť len jednu položku":t.maximum>=2&&t.maximum<=4?"Môžete zvoliť najviac "+e[t.maximum](!1)+" položky":"Môžete zvoliť najviac "+t.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/sr-Cyrl.js b/asset/static/libs/select2-4.0.3/js/i18n/sr-Cyrl.js new file mode 100644 index 0000000..e945394 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/sr-Cyrl.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr-Cyrl",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Обришите "+n+" симбол";return r+=e(n,"","а","а"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Укуцајте бар још "+n+" симбол";return r+=e(n,"","а","а"),r},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(t){var n="Можете изабрати само "+t.maximum+" ставк";return n+=e(t.maximum,"у","е","и"),n},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/sr.js b/asset/static/libs/select2-4.0.3/js/i18n/sr.js new file mode 100644 index 0000000..ac0cc72 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/sr.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/sv.js b/asset/static/libs/select2-4.0.3/js/i18n/sv.js new file mode 100644 index 0000000..bedac08 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/sv.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vänligen sudda ut "+t+" tecken";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vänligen skriv in "+t+" eller fler tecken";return n},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(e){var t="Du kan max välja "+e.maximum+" element";return t},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/th.js b/asset/static/libs/select2-4.0.3/js/i18n/th.js new file mode 100644 index 0000000..097a86c --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/th.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/th",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="โปรดลบออก "+t+" ตัวอักษร";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="โปรดพิมพ์เพิ่มอีก "+t+" ตัวอักษร";return n},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(e){var t="คุณสามารถเลือกได้ไม่เกิน "+e.maximum+" รายการ";return t},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/tr.js b/asset/static/libs/select2-4.0.3/js/i18n/tr.js new file mode 100644 index 0000000..25d27a8 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/tr.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/tr",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" karakter daha girmelisiniz";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="En az "+t+" karakter daha girmelisiniz";return n},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(e){var t="Sadece "+e.maximum+" seçim yapabilirsiniz";return t},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/uk.js b/asset/static/libs/select2-4.0.3/js/i18n/uk.js new file mode 100644 index 0000000..eb3ca89 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/uk.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/uk",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Будь ласка, видаліть "+n+" "+e(t.maximum,"літеру","літери","літер")},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Будь ласка, введіть "+t+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(t){return"Ви можете вибрати лише "+t.maximum+" "+e(t.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/vi.js b/asset/static/libs/select2-4.0.3/js/i18n/vi.js new file mode 100644 index 0000000..8975b8a --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/vi.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/vi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vui lòng nhập ít hơn "+t+" ký tự";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vui lòng nhập nhiều hơn "+t+' ký tự"';return n},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(e){var t="Chỉ có thể chọn được "+e.maximum+" lựa chọn";return t},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/zh-CN.js b/asset/static/libs/select2-4.0.3/js/i18n/zh-CN.js new file mode 100644 index 0000000..2ed9597 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/zh-CN.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="请删除"+t+"个字符";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="请再输入至少"+t+"个字符";return n},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(e){var t="最多只能选择"+e.maximum+"个项目";return t},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/i18n/zh-TW.js b/asset/static/libs/select2-4.0.3/js/i18n/zh-TW.js new file mode 100644 index 0000000..ea0812e --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/i18n/zh-TW.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */ + +(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="請刪掉"+t+"個字元";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="請再輸入"+t+"個字元";return n},loadingMore:function(){return"載入中…"},maximumSelected:function(e){var t="你只能選擇最多"+e.maximum+"項";return t},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"}}}),{define:e.define,require:e.require}})(); \ No newline at end of file diff --git a/asset/static/libs/select2-4.0.3/js/select2.full.js b/asset/static/libs/select2-4.0.3/js/select2.full.js new file mode 100644 index 0000000..e750834 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/select2.full.js @@ -0,0 +1,6436 @@ +/*! + * Select2 4.0.3 + * https://select2.github.io + * + * Released under the MIT license + * https://github.com/select2/select2/blob/master/LICENSE.md + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +}(function (jQuery) { + // This is needed so we can catch the AMD loader configuration and use it + // The inner file should be wrapped (by `banner.start.js`) in a function that + // returns the AMD loader references. + var S2 = +(function () { + // Restore the Select2 AMD loader so it can be used + // Needed mostly in the language files, where the loader is not inserted + if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { + var S2 = jQuery.fn.select2.amd; + } +var S2;(function () { if (!S2 || !S2.requirejs) { +if (!S2) { S2 = {}; } else { require = S2; } +/** + * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*jslint sloppy: true */ +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice, + jsSuffixRegExp = /\.js$/; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, lastIndex, + foundI, foundStarMap, starI, i, j, part, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name && name.charAt(0) === ".") { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + name = name.split('/'); + lastIndex = name.length - 1; + + // Node .js allowance: + if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { + name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); + } + + //Lop off the last part of baseParts, so that . matches the + //"directory" and not name of the baseName's module. For instance, + //baseName of "one/two/three", maps to "one/two/three.js", but we + //want the directory, "one/two" for this normalization. + name = baseParts.slice(0, baseParts.length - 1).concat(name); + + //start trimDots + for (i = 0; i < name.length; i += 1) { + part = name[i]; + if (part === ".") { + name.splice(i, 1); + i -= 1; + } else if (part === "..") { + if (i === 1 && (name[2] === '..' || name[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join("/"); + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + var args = aps.call(arguments, 0); + + //If first arg is not require('string'), and there is only + //one arg, it is the array form without a callback. Insert + //a null so that the following concat is correct. + if (typeof args[0] !== 'string' && args.length === 1) { + args.push(null); + } + return req.apply(undef, args.concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relName) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relName)); + } else { + name = normalize(name, relName); + } + } else { + name = normalize(name, relName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, + args = [], + callbackType = typeof callback, + usingExports; + + //Use name if no relName + relName = relName || name; + + //Call the callback to define the module, if necessary. + if (callbackType === 'undefined' || callbackType === 'function') { + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relName); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback ? callback.apply(defined[name], args) : undefined; + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, callback).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (config.deps) { + req(config.deps, config.callback); + } + if (!callback) { + return; + } + + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + return req(cfg); + }; + + /** + * Expose module registry for debugging and tooling + */ + requirejs._defined = defined; + + define = function (name, deps, callback) { + if (typeof name !== 'string') { + throw new Error('See almond README: incorrect module build, no module name'); + } + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); + +S2.requirejs = requirejs;S2.require = require;S2.define = define; +} +}()); +S2.define("almond", function(){}); + +/* global jQuery:false, $:false */ +S2.define('jquery',[],function () { + var _$ = jQuery || $; + + if (_$ == null && console && console.error) { + console.error( + 'Select2: An instance of jQuery or a jQuery-compatible library was not ' + + 'found. Make sure that you are including jQuery before Select2 on your ' + + 'web page.' + ); + } + + return _$; +}); + +S2.define('select2/utils',[ + 'jquery' +], function ($) { + var Utils = {}; + + Utils.Extend = function (ChildClass, SuperClass) { + var __hasProp = {}.hasOwnProperty; + + function BaseConstructor () { + this.constructor = ChildClass; + } + + for (var key in SuperClass) { + if (__hasProp.call(SuperClass, key)) { + ChildClass[key] = SuperClass[key]; + } + } + + BaseConstructor.prototype = SuperClass.prototype; + ChildClass.prototype = new BaseConstructor(); + ChildClass.__super__ = SuperClass.prototype; + + return ChildClass; + }; + + function getMethods (theClass) { + var proto = theClass.prototype; + + var methods = []; + + for (var methodName in proto) { + var m = proto[methodName]; + + if (typeof m !== 'function') { + continue; + } + + if (methodName === 'constructor') { + continue; + } + + methods.push(methodName); + } + + return methods; + } + + Utils.Decorate = function (SuperClass, DecoratorClass) { + var decoratedMethods = getMethods(DecoratorClass); + var superMethods = getMethods(SuperClass); + + function DecoratedClass () { + var unshift = Array.prototype.unshift; + + var argCount = DecoratorClass.prototype.constructor.length; + + var calledConstructor = SuperClass.prototype.constructor; + + if (argCount > 0) { + unshift.call(arguments, SuperClass.prototype.constructor); + + calledConstructor = DecoratorClass.prototype.constructor; + } + + calledConstructor.apply(this, arguments); + } + + DecoratorClass.displayName = SuperClass.displayName; + + function ctr () { + this.constructor = DecoratedClass; + } + + DecoratedClass.prototype = new ctr(); + + for (var m = 0; m < superMethods.length; m++) { + var superMethod = superMethods[m]; + + DecoratedClass.prototype[superMethod] = + SuperClass.prototype[superMethod]; + } + + var calledMethod = function (methodName) { + // Stub out the original method if it's not decorating an actual method + var originalMethod = function () {}; + + if (methodName in DecoratedClass.prototype) { + originalMethod = DecoratedClass.prototype[methodName]; + } + + var decoratedMethod = DecoratorClass.prototype[methodName]; + + return function () { + var unshift = Array.prototype.unshift; + + unshift.call(arguments, originalMethod); + + return decoratedMethod.apply(this, arguments); + }; + }; + + for (var d = 0; d < decoratedMethods.length; d++) { + var decoratedMethod = decoratedMethods[d]; + + DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod); + } + + return DecoratedClass; + }; + + var Observable = function () { + this.listeners = {}; + }; + + Observable.prototype.on = function (event, callback) { + this.listeners = this.listeners || {}; + + if (event in this.listeners) { + this.listeners[event].push(callback); + } else { + this.listeners[event] = [callback]; + } + }; + + Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + var params = slice.call(arguments, 1); + + this.listeners = this.listeners || {}; + + // Params should always come in as an array + if (params == null) { + params = []; + } + + // If there are no arguments to the event, use a temporary object + if (params.length === 0) { + params.push({}); + } + + // Set the `_type` of the first object to the event + params[0]._type = event; + + if (event in this.listeners) { + this.invoke(this.listeners[event], slice.call(arguments, 1)); + } + + if ('*' in this.listeners) { + this.invoke(this.listeners['*'], arguments); + } + }; + + Observable.prototype.invoke = function (listeners, params) { + for (var i = 0, len = listeners.length; i < len; i++) { + listeners[i].apply(this, params); + } + }; + + Utils.Observable = Observable; + + Utils.generateChars = function (length) { + var chars = ''; + + for (var i = 0; i < length; i++) { + var randomChar = Math.floor(Math.random() * 36); + chars += randomChar.toString(36); + } + + return chars; + }; + + Utils.bind = function (func, context) { + return function () { + func.apply(context, arguments); + }; + }; + + Utils._convertData = function (data) { + for (var originalKey in data) { + var keys = originalKey.split('-'); + + var dataLevel = data; + + if (keys.length === 1) { + continue; + } + + for (var k = 0; k < keys.length; k++) { + var key = keys[k]; + + // Lowercase the first letter + // By default, dash-separated becomes camelCase + key = key.substring(0, 1).toLowerCase() + key.substring(1); + + if (!(key in dataLevel)) { + dataLevel[key] = {}; + } + + if (k == keys.length - 1) { + dataLevel[key] = data[originalKey]; + } + + dataLevel = dataLevel[key]; + } + + delete data[originalKey]; + } + + return data; + }; + + Utils.hasScroll = function (index, el) { + // Adapted from the function created by @ShadowScripter + // and adapted by @BillBarry on the Stack Exchange Code Review website. + // The original code can be found at + // http://codereview.stackexchange.com/q/13338 + // and was designed to be used with the Sizzle selector engine. + + var $el = $(el); + var overflowX = el.style.overflowX; + var overflowY = el.style.overflowY; + + //Check both x and y declarations + if (overflowX === overflowY && + (overflowY === 'hidden' || overflowY === 'visible')) { + return false; + } + + if (overflowX === 'scroll' || overflowY === 'scroll') { + return true; + } + + return ($el.innerHeight() < el.scrollHeight || + $el.innerWidth() < el.scrollWidth); + }; + + Utils.escapeMarkup = function (markup) { + var replaceMap = { + '\\': '\', + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '/': '/' + }; + + // Do not try to escape the markup if it's not a string + if (typeof markup !== 'string') { + return markup; + } + + return String(markup).replace(/[&<>"'\/\\]/g, function (match) { + return replaceMap[match]; + }); + }; + + // Append an array of jQuery nodes to a given element. + Utils.appendMany = function ($element, $nodes) { + // jQuery 1.7.x does not support $.fn.append() with an array + // Fall back to a jQuery object collection using $.fn.add() + if ($.fn.jquery.substr(0, 3) === '1.7') { + var $jqNodes = $(); + + $.map($nodes, function (node) { + $jqNodes = $jqNodes.add(node); + }); + + $nodes = $jqNodes; + } + + $element.append($nodes); + }; + + return Utils; +}); + +S2.define('select2/results',[ + 'jquery', + './utils' +], function ($, Utils) { + function Results ($element, options, dataAdapter) { + this.$element = $element; + this.data = dataAdapter; + this.options = options; + + Results.__super__.constructor.call(this); + } + + Utils.Extend(Results, Utils.Observable); + + Results.prototype.render = function () { + var $results = $( + '
    ' + ); + + if (this.options.get('multiple')) { + $results.attr('aria-multiselectable', 'true'); + } + + this.$results = $results; + + return $results; + }; + + Results.prototype.clear = function () { + this.$results.empty(); + }; + + Results.prototype.displayMessage = function (params) { + var escapeMarkup = this.options.get('escapeMarkup'); + + this.clear(); + this.hideLoading(); + + var $message = $( + '
  • ' + ); + + var message = this.options.get('translations').get(params.message); + + $message.append( + escapeMarkup( + message(params.args) + ) + ); + + $message[0].className += ' select2-results__message'; + + this.$results.append($message); + }; + + Results.prototype.hideMessages = function () { + this.$results.find('.select2-results__message').remove(); + }; + + Results.prototype.append = function (data) { + this.hideLoading(); + + var $options = []; + + if (data.results == null || data.results.length === 0) { + if (this.$results.children().length === 0) { + this.trigger('results:message', { + message: 'noResults' + }); + } + + return; + } + + data.results = this.sort(data.results); + + for (var d = 0; d < data.results.length; d++) { + var item = data.results[d]; + + var $option = this.option(item); + + $options.push($option); + } + + this.$results.append($options); + }; + + Results.prototype.position = function ($results, $dropdown) { + var $resultsContainer = $dropdown.find('.select2-results'); + $resultsContainer.append($results); + }; + + Results.prototype.sort = function (data) { + var sorter = this.options.get('sorter'); + + return sorter(data); + }; + + Results.prototype.highlightFirstItem = function () { + var $options = this.$results + .find('.select2-results__option[aria-selected]'); + + var $selected = $options.filter('[aria-selected=true]'); + + // Check if there are any selected options + if ($selected.length > 0) { + // If there are selected options, highlight the first + $selected.first().trigger('mouseenter'); + } else { + // If there are no selected options, highlight the first option + // in the dropdown + $options.first().trigger('mouseenter'); + } + + this.ensureHighlightVisible(); + }; + + Results.prototype.setClasses = function () { + var self = this; + + this.data.current(function (selected) { + var selectedIds = $.map(selected, function (s) { + return s.id.toString(); + }); + + var $options = self.$results + .find('.select2-results__option[aria-selected]'); + + $options.each(function () { + var $option = $(this); + + var item = $.data(this, 'data'); + + // id needs to be converted to a string when comparing + var id = '' + item.id; + + if ((item.element != null && item.element.selected) || + (item.element == null && $.inArray(id, selectedIds) > -1)) { + $option.attr('aria-selected', 'true'); + } else { + $option.attr('aria-selected', 'false'); + } + }); + + }); + }; + + Results.prototype.showLoading = function (params) { + this.hideLoading(); + + var loadingMore = this.options.get('translations').get('searching'); + + var loading = { + disabled: true, + loading: true, + text: loadingMore(params) + }; + var $loading = this.option(loading); + $loading.className += ' loading-results'; + + this.$results.prepend($loading); + }; + + Results.prototype.hideLoading = function () { + this.$results.find('.loading-results').remove(); + }; + + Results.prototype.option = function (data) { + var option = document.createElement('li'); + option.className = 'select2-results__option'; + + var attrs = { + 'role': 'treeitem', + 'aria-selected': 'false' + }; + + if (data.disabled) { + delete attrs['aria-selected']; + attrs['aria-disabled'] = 'true'; + } + + if (data.id == null) { + delete attrs['aria-selected']; + } + + if (data._resultId != null) { + option.id = data._resultId; + } + + if (data.title) { + option.title = data.title; + } + + if (data.children) { + attrs.role = 'group'; + attrs['aria-label'] = data.text; + delete attrs['aria-selected']; + } + + for (var attr in attrs) { + var val = attrs[attr]; + + option.setAttribute(attr, val); + } + + if (data.children) { + var $option = $(option); + + var label = document.createElement('strong'); + label.className = 'select2-results__group'; + + var $label = $(label); + this.template(data, label); + + var $children = []; + + for (var c = 0; c < data.children.length; c++) { + var child = data.children[c]; + + var $child = this.option(child); + + $children.push($child); + } + + var $childrenContainer = $('
      ', { + 'class': 'select2-results__options select2-results__options--nested' + }); + + $childrenContainer.append($children); + + $option.append(label); + $option.append($childrenContainer); + } else { + this.template(data, option); + } + + $.data(option, 'data', data); + + return option; + }; + + Results.prototype.bind = function (container, $container) { + var self = this; + + var id = container.id + '-results'; + + this.$results.attr('id', id); + + container.on('results:all', function (params) { + self.clear(); + self.append(params.data); + + if (container.isOpen()) { + self.setClasses(); + self.highlightFirstItem(); + } + }); + + container.on('results:append', function (params) { + self.append(params.data); + + if (container.isOpen()) { + self.setClasses(); + } + }); + + container.on('query', function (params) { + self.hideMessages(); + self.showLoading(params); + }); + + container.on('select', function () { + if (!container.isOpen()) { + return; + } + + self.setClasses(); + self.highlightFirstItem(); + }); + + container.on('unselect', function () { + if (!container.isOpen()) { + return; + } + + self.setClasses(); + self.highlightFirstItem(); + }); + + container.on('open', function () { + // When the dropdown is open, aria-expended="true" + self.$results.attr('aria-expanded', 'true'); + self.$results.attr('aria-hidden', 'false'); + + self.setClasses(); + self.ensureHighlightVisible(); + }); + + container.on('close', function () { + // When the dropdown is closed, aria-expended="false" + self.$results.attr('aria-expanded', 'false'); + self.$results.attr('aria-hidden', 'true'); + self.$results.removeAttr('aria-activedescendant'); + }); + + container.on('results:toggle', function () { + var $highlighted = self.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + $highlighted.trigger('mouseup'); + }); + + container.on('results:select', function () { + var $highlighted = self.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + var data = $highlighted.data('data'); + + if ($highlighted.attr('aria-selected') == 'true') { + self.trigger('close', {}); + } else { + self.trigger('select', { + data: data + }); + } + }); + + container.on('results:previous', function () { + var $highlighted = self.getHighlightedResults(); + + var $options = self.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + // If we are already at te top, don't move further + if (currentIndex === 0) { + return; + } + + var nextIndex = currentIndex - 1; + + // If none are highlighted, highlight the first + if ($highlighted.length === 0) { + nextIndex = 0; + } + + var $next = $options.eq(nextIndex); + + $next.trigger('mouseenter'); + + var currentOffset = self.$results.offset().top; + var nextTop = $next.offset().top; + var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset); + + if (nextIndex === 0) { + self.$results.scrollTop(0); + } else if (nextTop - currentOffset < 0) { + self.$results.scrollTop(nextOffset); + } + }); + + container.on('results:next', function () { + var $highlighted = self.getHighlightedResults(); + + var $options = self.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + var nextIndex = currentIndex + 1; + + // If we are at the last option, stay there + if (nextIndex >= $options.length) { + return; + } + + var $next = $options.eq(nextIndex); + + $next.trigger('mouseenter'); + + var currentOffset = self.$results.offset().top + + self.$results.outerHeight(false); + var nextBottom = $next.offset().top + $next.outerHeight(false); + var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset; + + if (nextIndex === 0) { + self.$results.scrollTop(0); + } else if (nextBottom > currentOffset) { + self.$results.scrollTop(nextOffset); + } + }); + + container.on('results:focus', function (params) { + params.element.addClass('select2-results__option--highlighted'); + }); + + container.on('results:message', function (params) { + self.displayMessage(params); + }); + + if ($.fn.mousewheel) { + this.$results.on('mousewheel', function (e) { + var top = self.$results.scrollTop(); + + var bottom = self.$results.get(0).scrollHeight - top + e.deltaY; + + var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0; + var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height(); + + if (isAtTop) { + self.$results.scrollTop(0); + + e.preventDefault(); + e.stopPropagation(); + } else if (isAtBottom) { + self.$results.scrollTop( + self.$results.get(0).scrollHeight - self.$results.height() + ); + + e.preventDefault(); + e.stopPropagation(); + } + }); + } + + this.$results.on('mouseup', '.select2-results__option[aria-selected]', + function (evt) { + var $this = $(this); + + var data = $this.data('data'); + + if ($this.attr('aria-selected') === 'true') { + if (self.options.get('multiple')) { + self.trigger('unselect', { + originalEvent: evt, + data: data + }); + } else { + self.trigger('close', {}); + } + + return; + } + + self.trigger('select', { + originalEvent: evt, + data: data + }); + }); + + this.$results.on('mouseenter', '.select2-results__option[aria-selected]', + function (evt) { + var data = $(this).data('data'); + + self.getHighlightedResults() + .removeClass('select2-results__option--highlighted'); + + self.trigger('results:focus', { + data: data, + element: $(this) + }); + }); + }; + + Results.prototype.getHighlightedResults = function () { + var $highlighted = this.$results + .find('.select2-results__option--highlighted'); + + return $highlighted; + }; + + Results.prototype.destroy = function () { + this.$results.remove(); + }; + + Results.prototype.ensureHighlightVisible = function () { + var $highlighted = this.getHighlightedResults(); + + if ($highlighted.length === 0) { + return; + } + + var $options = this.$results.find('[aria-selected]'); + + var currentIndex = $options.index($highlighted); + + var currentOffset = this.$results.offset().top; + var nextTop = $highlighted.offset().top; + var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset); + + var offsetDelta = nextTop - currentOffset; + nextOffset -= $highlighted.outerHeight(false) * 2; + + if (currentIndex <= 2) { + this.$results.scrollTop(0); + } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) { + this.$results.scrollTop(nextOffset); + } + }; + + Results.prototype.template = function (result, container) { + var template = this.options.get('templateResult'); + var escapeMarkup = this.options.get('escapeMarkup'); + + var content = template(result, container); + + if (content == null) { + container.style.display = 'none'; + } else if (typeof content === 'string') { + container.innerHTML = escapeMarkup(content); + } else { + $(container).append(content); + } + }; + + return Results; +}); + +S2.define('select2/keys',[ + +], function () { + var KEYS = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + DELETE: 46 + }; + + return KEYS; +}); + +S2.define('select2/selection/base',[ + 'jquery', + '../utils', + '../keys' +], function ($, Utils, KEYS) { + function BaseSelection ($element, options) { + this.$element = $element; + this.options = options; + + BaseSelection.__super__.constructor.call(this); + } + + Utils.Extend(BaseSelection, Utils.Observable); + + BaseSelection.prototype.render = function () { + var $selection = $( + '' + ); + + this._tabindex = 0; + + if (this.$element.data('old-tabindex') != null) { + this._tabindex = this.$element.data('old-tabindex'); + } else if (this.$element.attr('tabindex') != null) { + this._tabindex = this.$element.attr('tabindex'); + } + + $selection.attr('title', this.$element.attr('title')); + $selection.attr('tabindex', this._tabindex); + + this.$selection = $selection; + + return $selection; + }; + + BaseSelection.prototype.bind = function (container, $container) { + var self = this; + + var id = container.id + '-container'; + var resultsId = container.id + '-results'; + + this.container = container; + + this.$selection.on('focus', function (evt) { + self.trigger('focus', evt); + }); + + this.$selection.on('blur', function (evt) { + self._handleBlur(evt); + }); + + this.$selection.on('keydown', function (evt) { + self.trigger('keypress', evt); + + if (evt.which === KEYS.SPACE) { + evt.preventDefault(); + } + }); + + container.on('results:focus', function (params) { + self.$selection.attr('aria-activedescendant', params.data._resultId); + }); + + container.on('selection:update', function (params) { + self.update(params.data); + }); + + container.on('open', function () { + // When the dropdown is open, aria-expanded="true" + self.$selection.attr('aria-expanded', 'true'); + self.$selection.attr('aria-owns', resultsId); + + self._attachCloseHandler(container); + }); + + container.on('close', function () { + // When the dropdown is closed, aria-expanded="false" + self.$selection.attr('aria-expanded', 'false'); + self.$selection.removeAttr('aria-activedescendant'); + self.$selection.removeAttr('aria-owns'); + + self.$selection.focus(); + + self._detachCloseHandler(container); + }); + + container.on('enable', function () { + self.$selection.attr('tabindex', self._tabindex); + }); + + container.on('disable', function () { + self.$selection.attr('tabindex', '-1'); + }); + }; + + BaseSelection.prototype._handleBlur = function (evt) { + var self = this; + + // This needs to be delayed as the active element is the body when the tab + // key is pressed, possibly along with others. + window.setTimeout(function () { + // Don't trigger `blur` if the focus is still in the selection + if ( + (document.activeElement == self.$selection[0]) || + ($.contains(self.$selection[0], document.activeElement)) + ) { + return; + } + + self.trigger('blur', evt); + }, 1); + }; + + BaseSelection.prototype._attachCloseHandler = function (container) { + var self = this; + + $(document.body).on('mousedown.select2.' + container.id, function (e) { + var $target = $(e.target); + + var $select = $target.closest('.select2'); + + var $all = $('.select2.select2-container--open'); + + $all.each(function () { + var $this = $(this); + + if (this == $select[0]) { + return; + } + + var $element = $this.data('element'); + + $element.select2('close'); + }); + }); + }; + + BaseSelection.prototype._detachCloseHandler = function (container) { + $(document.body).off('mousedown.select2.' + container.id); + }; + + BaseSelection.prototype.position = function ($selection, $container) { + var $selectionContainer = $container.find('.selection'); + $selectionContainer.append($selection); + }; + + BaseSelection.prototype.destroy = function () { + this._detachCloseHandler(this.container); + }; + + BaseSelection.prototype.update = function (data) { + throw new Error('The `update` method must be defined in child classes.'); + }; + + return BaseSelection; +}); + +S2.define('select2/selection/single',[ + 'jquery', + './base', + '../utils', + '../keys' +], function ($, BaseSelection, Utils, KEYS) { + function SingleSelection () { + SingleSelection.__super__.constructor.apply(this, arguments); + } + + Utils.Extend(SingleSelection, BaseSelection); + + SingleSelection.prototype.render = function () { + var $selection = SingleSelection.__super__.render.call(this); + + $selection.addClass('select2-selection--single'); + + $selection.html( + '' + + '' + + '' + + '' + ); + + return $selection; + }; + + SingleSelection.prototype.bind = function (container, $container) { + var self = this; + + SingleSelection.__super__.bind.apply(this, arguments); + + var id = container.id + '-container'; + + this.$selection.find('.select2-selection__rendered').attr('id', id); + this.$selection.attr('aria-labelledby', id); + + this.$selection.on('mousedown', function (evt) { + // Only respond to left clicks + if (evt.which !== 1) { + return; + } + + self.trigger('toggle', { + originalEvent: evt + }); + }); + + this.$selection.on('focus', function (evt) { + // User focuses on the container + }); + + this.$selection.on('blur', function (evt) { + // User exits the container + }); + + container.on('focus', function (evt) { + if (!container.isOpen()) { + self.$selection.focus(); + } + }); + + container.on('selection:update', function (params) { + self.update(params.data); + }); + }; + + SingleSelection.prototype.clear = function () { + this.$selection.find('.select2-selection__rendered').empty(); + }; + + SingleSelection.prototype.display = function (data, container) { + var template = this.options.get('templateSelection'); + var escapeMarkup = this.options.get('escapeMarkup'); + + return escapeMarkup(template(data, container)); + }; + + SingleSelection.prototype.selectionContainer = function () { + return $(''); + }; + + SingleSelection.prototype.update = function (data) { + if (data.length === 0) { + this.clear(); + return; + } + + var selection = data[0]; + + var $rendered = this.$selection.find('.select2-selection__rendered'); + var formatted = this.display(selection, $rendered); + + $rendered.empty().append(formatted); + $rendered.prop('title', selection.title || selection.text); + }; + + return SingleSelection; +}); + +S2.define('select2/selection/multiple',[ + 'jquery', + './base', + '../utils' +], function ($, BaseSelection, Utils) { + function MultipleSelection ($element, options) { + MultipleSelection.__super__.constructor.apply(this, arguments); + } + + Utils.Extend(MultipleSelection, BaseSelection); + + MultipleSelection.prototype.render = function () { + var $selection = MultipleSelection.__super__.render.call(this); + + $selection.addClass('select2-selection--multiple'); + + $selection.html( + '
        ' + ); + + return $selection; + }; + + MultipleSelection.prototype.bind = function (container, $container) { + var self = this; + + MultipleSelection.__super__.bind.apply(this, arguments); + + this.$selection.on('click', function (evt) { + self.trigger('toggle', { + originalEvent: evt + }); + }); + + this.$selection.on( + 'click', + '.select2-selection__choice__remove', + function (evt) { + // Ignore the event if it is disabled + if (self.options.get('disabled')) { + return; + } + + var $remove = $(this); + var $selection = $remove.parent(); + + var data = $selection.data('data'); + + self.trigger('unselect', { + originalEvent: evt, + data: data + }); + } + ); + }; + + MultipleSelection.prototype.clear = function () { + this.$selection.find('.select2-selection__rendered').empty(); + }; + + MultipleSelection.prototype.display = function (data, container) { + var template = this.options.get('templateSelection'); + var escapeMarkup = this.options.get('escapeMarkup'); + + return escapeMarkup(template(data, container)); + }; + + MultipleSelection.prototype.selectionContainer = function () { + var $container = $( + '
      • ' + + '' + + '×' + + '' + + '
      • ' + ); + + return $container; + }; + + MultipleSelection.prototype.update = function (data) { + this.clear(); + + if (data.length === 0) { + return; + } + + var $selections = []; + + for (var d = 0; d < data.length; d++) { + var selection = data[d]; + + var $selection = this.selectionContainer(); + var formatted = this.display(selection, $selection); + + $selection.append(formatted); + $selection.prop('title', selection.title || selection.text); + + $selection.data('data', selection); + + $selections.push($selection); + } + + var $rendered = this.$selection.find('.select2-selection__rendered'); + + Utils.appendMany($rendered, $selections); + }; + + return MultipleSelection; +}); + +S2.define('select2/selection/placeholder',[ + '../utils' +], function (Utils) { + function Placeholder (decorated, $element, options) { + this.placeholder = this.normalizePlaceholder(options.get('placeholder')); + + decorated.call(this, $element, options); + } + + Placeholder.prototype.normalizePlaceholder = function (_, placeholder) { + if (typeof placeholder === 'string') { + placeholder = { + id: '', + text: placeholder + }; + } + + return placeholder; + }; + + Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { + var $placeholder = this.selectionContainer(); + + $placeholder.html(this.display(placeholder)); + $placeholder.addClass('select2-selection__placeholder') + .removeClass('select2-selection__choice'); + + return $placeholder; + }; + + Placeholder.prototype.update = function (decorated, data) { + var singlePlaceholder = ( + data.length == 1 && data[0].id != this.placeholder.id + ); + var multipleSelections = data.length > 1; + + if (multipleSelections || singlePlaceholder) { + return decorated.call(this, data); + } + + this.clear(); + + var $placeholder = this.createPlaceholder(this.placeholder); + + this.$selection.find('.select2-selection__rendered').append($placeholder); + }; + + return Placeholder; +}); + +S2.define('select2/selection/allowClear',[ + 'jquery', + '../keys' +], function ($, KEYS) { + function AllowClear () { } + + AllowClear.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + if (this.placeholder == null) { + if (this.options.get('debug') && window.console && console.error) { + console.error( + 'Select2: The `allowClear` option should be used in combination ' + + 'with the `placeholder` option.' + ); + } + } + + this.$selection.on('mousedown', '.select2-selection__clear', + function (evt) { + self._handleClear(evt); + }); + + container.on('keypress', function (evt) { + self._handleKeyboardClear(evt, container); + }); + }; + + AllowClear.prototype._handleClear = function (_, evt) { + // Ignore the event if it is disabled + if (this.options.get('disabled')) { + return; + } + + var $clear = this.$selection.find('.select2-selection__clear'); + + // Ignore the event if nothing has been selected + if ($clear.length === 0) { + return; + } + + evt.stopPropagation(); + + var data = $clear.data('data'); + + for (var d = 0; d < data.length; d++) { + var unselectData = { + data: data[d] + }; + + // Trigger the `unselect` event, so people can prevent it from being + // cleared. + this.trigger('unselect', unselectData); + + // If the event was prevented, don't clear it out. + if (unselectData.prevented) { + return; + } + } + + this.$element.val(this.placeholder.id).trigger('change'); + + this.trigger('toggle', {}); + }; + + AllowClear.prototype._handleKeyboardClear = function (_, evt, container) { + if (container.isOpen()) { + return; + } + + if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) { + this._handleClear(evt); + } + }; + + AllowClear.prototype.update = function (decorated, data) { + decorated.call(this, data); + + if (this.$selection.find('.select2-selection__placeholder').length > 0 || + data.length === 0) { + return; + } + + var $remove = $( + '' + + '×' + + '' + ); + $remove.data('data', data); + + this.$selection.find('.select2-selection__rendered').prepend($remove); + }; + + return AllowClear; +}); + +S2.define('select2/selection/search',[ + 'jquery', + '../utils', + '../keys' +], function ($, Utils, KEYS) { + function Search (decorated, $element, options) { + decorated.call(this, $element, options); + } + + Search.prototype.render = function (decorated) { + var $search = $( + '' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + var $rendered = decorated.call(this); + + this._transferTabIndex(); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('open', function () { + self.$search.trigger('focus'); + }); + + container.on('close', function () { + self.$search.val(''); + self.$search.removeAttr('aria-activedescendant'); + self.$search.trigger('focus'); + }); + + container.on('enable', function () { + self.$search.prop('disabled', false); + + self._transferTabIndex(); + }); + + container.on('disable', function () { + self.$search.prop('disabled', true); + }); + + container.on('focus', function (evt) { + self.$search.trigger('focus'); + }); + + container.on('results:focus', function (params) { + self.$search.attr('aria-activedescendant', params.id); + }); + + this.$selection.on('focusin', '.select2-search--inline', function (evt) { + self.trigger('focus', evt); + }); + + this.$selection.on('focusout', '.select2-search--inline', function (evt) { + self._handleBlur(evt); + }); + + this.$selection.on('keydown', '.select2-search--inline', function (evt) { + evt.stopPropagation(); + + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + + var key = evt.which; + + if (key === KEYS.BACKSPACE && self.$search.val() === '') { + var $previousChoice = self.$searchContainer + .prev('.select2-selection__choice'); + + if ($previousChoice.length > 0) { + var item = $previousChoice.data('data'); + + self.searchRemoveChoice(item); + + evt.preventDefault(); + } + } + }); + + // Try to detect the IE version should the `documentMode` property that + // is stored on the document. This is only implemented in IE and is + // slightly cleaner than doing a user agent check. + // This property is not available in Edge, but Edge also doesn't have + // this bug. + var msie = document.documentMode; + var disableInputEvents = msie && msie <= 11; + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$selection.on( + 'input.searchcheck', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents) { + self.$selection.off('input.search input.searchcheck'); + return; + } + + // Unbind the duplicated `keyup` event + self.$selection.off('keyup.search'); + } + ); + + this.$selection.on( + 'keyup.search input.search', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents && evt.type === 'input') { + self.$selection.off('input.search input.searchcheck'); + return; + } + + var key = evt.which; + + // We can freely ignore events from modifier keys + if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { + return; + } + + // Tabbing will be handled during the `keydown` phase + if (key == KEYS.TAB) { + return; + } + + self.handleSearch(evt); + } + ); + }; + + /** + * This method will transfer the tabindex attribute from the rendered + * selection to the search box. This allows for the search box to be used as + * the primary focus instead of the selection container. + * + * @private + */ + Search.prototype._transferTabIndex = function (decorated) { + this.$search.attr('tabindex', this.$selection.attr('tabindex')); + this.$selection.attr('tabindex', '-1'); + }; + + Search.prototype.createPlaceholder = function (decorated, placeholder) { + this.$search.attr('placeholder', placeholder.text); + }; + + Search.prototype.update = function (decorated, data) { + var searchHadFocus = this.$search[0] == document.activeElement; + + this.$search.attr('placeholder', ''); + + decorated.call(this, data); + + this.$selection.find('.select2-selection__rendered') + .append(this.$searchContainer); + + this.resizeSearch(); + if (searchHadFocus) { + this.$search.focus(); + } + }; + + Search.prototype.handleSearch = function () { + this.resizeSearch(); + + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.searchRemoveChoice = function (decorated, item) { + this.trigger('unselect', { + data: item + }); + + this.$search.val(item.text); + this.handleSearch(); + }; + + Search.prototype.resizeSearch = function () { + this.$search.css('width', '25px'); + + var width = ''; + + if (this.$search.attr('placeholder') !== '') { + width = this.$selection.find('.select2-selection__rendered').innerWidth(); + } else { + var minimumWidth = this.$search.val().length + 1; + + width = (minimumWidth * 0.75) + 'em'; + } + + this.$search.css('width', width); + }; + + return Search; +}); + +S2.define('select2/selection/eventRelay',[ + 'jquery' +], function ($) { + function EventRelay () { } + + EventRelay.prototype.bind = function (decorated, container, $container) { + var self = this; + var relayEvents = [ + 'open', 'opening', + 'close', 'closing', + 'select', 'selecting', + 'unselect', 'unselecting' + ]; + + var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting']; + + decorated.call(this, container, $container); + + container.on('*', function (name, params) { + // Ignore events that should not be relayed + if ($.inArray(name, relayEvents) === -1) { + return; + } + + // The parameters should always be an object + params = params || {}; + + // Generate the jQuery event for the Select2 event + var evt = $.Event('select2:' + name, { + params: params + }); + + self.$element.trigger(evt); + + // Only handle preventable events if it was one + if ($.inArray(name, preventableEvents) === -1) { + return; + } + + params.prevented = evt.isDefaultPrevented(); + }); + }; + + return EventRelay; +}); + +S2.define('select2/translation',[ + 'jquery', + 'require' +], function ($, require) { + function Translation (dict) { + this.dict = dict || {}; + } + + Translation.prototype.all = function () { + return this.dict; + }; + + Translation.prototype.get = function (key) { + return this.dict[key]; + }; + + Translation.prototype.extend = function (translation) { + this.dict = $.extend({}, translation.all(), this.dict); + }; + + // Static functions + + Translation._cache = {}; + + Translation.loadPath = function (path) { + if (!(path in Translation._cache)) { + var translations = require(path); + + Translation._cache[path] = translations; + } + + return new Translation(Translation._cache[path]); + }; + + return Translation; +}); + +S2.define('select2/diacritics',[ + +], function () { + var diacritics = { + '\u24B6': 'A', + '\uFF21': 'A', + '\u00C0': 'A', + '\u00C1': 'A', + '\u00C2': 'A', + '\u1EA6': 'A', + '\u1EA4': 'A', + '\u1EAA': 'A', + '\u1EA8': 'A', + '\u00C3': 'A', + '\u0100': 'A', + '\u0102': 'A', + '\u1EB0': 'A', + '\u1EAE': 'A', + '\u1EB4': 'A', + '\u1EB2': 'A', + '\u0226': 'A', + '\u01E0': 'A', + '\u00C4': 'A', + '\u01DE': 'A', + '\u1EA2': 'A', + '\u00C5': 'A', + '\u01FA': 'A', + '\u01CD': 'A', + '\u0200': 'A', + '\u0202': 'A', + '\u1EA0': 'A', + '\u1EAC': 'A', + '\u1EB6': 'A', + '\u1E00': 'A', + '\u0104': 'A', + '\u023A': 'A', + '\u2C6F': 'A', + '\uA732': 'AA', + '\u00C6': 'AE', + '\u01FC': 'AE', + '\u01E2': 'AE', + '\uA734': 'AO', + '\uA736': 'AU', + '\uA738': 'AV', + '\uA73A': 'AV', + '\uA73C': 'AY', + '\u24B7': 'B', + '\uFF22': 'B', + '\u1E02': 'B', + '\u1E04': 'B', + '\u1E06': 'B', + '\u0243': 'B', + '\u0182': 'B', + '\u0181': 'B', + '\u24B8': 'C', + '\uFF23': 'C', + '\u0106': 'C', + '\u0108': 'C', + '\u010A': 'C', + '\u010C': 'C', + '\u00C7': 'C', + '\u1E08': 'C', + '\u0187': 'C', + '\u023B': 'C', + '\uA73E': 'C', + '\u24B9': 'D', + '\uFF24': 'D', + '\u1E0A': 'D', + '\u010E': 'D', + '\u1E0C': 'D', + '\u1E10': 'D', + '\u1E12': 'D', + '\u1E0E': 'D', + '\u0110': 'D', + '\u018B': 'D', + '\u018A': 'D', + '\u0189': 'D', + '\uA779': 'D', + '\u01F1': 'DZ', + '\u01C4': 'DZ', + '\u01F2': 'Dz', + '\u01C5': 'Dz', + '\u24BA': 'E', + '\uFF25': 'E', + '\u00C8': 'E', + '\u00C9': 'E', + '\u00CA': 'E', + '\u1EC0': 'E', + '\u1EBE': 'E', + '\u1EC4': 'E', + '\u1EC2': 'E', + '\u1EBC': 'E', + '\u0112': 'E', + '\u1E14': 'E', + '\u1E16': 'E', + '\u0114': 'E', + '\u0116': 'E', + '\u00CB': 'E', + '\u1EBA': 'E', + '\u011A': 'E', + '\u0204': 'E', + '\u0206': 'E', + '\u1EB8': 'E', + '\u1EC6': 'E', + '\u0228': 'E', + '\u1E1C': 'E', + '\u0118': 'E', + '\u1E18': 'E', + '\u1E1A': 'E', + '\u0190': 'E', + '\u018E': 'E', + '\u24BB': 'F', + '\uFF26': 'F', + '\u1E1E': 'F', + '\u0191': 'F', + '\uA77B': 'F', + '\u24BC': 'G', + '\uFF27': 'G', + '\u01F4': 'G', + '\u011C': 'G', + '\u1E20': 'G', + '\u011E': 'G', + '\u0120': 'G', + '\u01E6': 'G', + '\u0122': 'G', + '\u01E4': 'G', + '\u0193': 'G', + '\uA7A0': 'G', + '\uA77D': 'G', + '\uA77E': 'G', + '\u24BD': 'H', + '\uFF28': 'H', + '\u0124': 'H', + '\u1E22': 'H', + '\u1E26': 'H', + '\u021E': 'H', + '\u1E24': 'H', + '\u1E28': 'H', + '\u1E2A': 'H', + '\u0126': 'H', + '\u2C67': 'H', + '\u2C75': 'H', + '\uA78D': 'H', + '\u24BE': 'I', + '\uFF29': 'I', + '\u00CC': 'I', + '\u00CD': 'I', + '\u00CE': 'I', + '\u0128': 'I', + '\u012A': 'I', + '\u012C': 'I', + '\u0130': 'I', + '\u00CF': 'I', + '\u1E2E': 'I', + '\u1EC8': 'I', + '\u01CF': 'I', + '\u0208': 'I', + '\u020A': 'I', + '\u1ECA': 'I', + '\u012E': 'I', + '\u1E2C': 'I', + '\u0197': 'I', + '\u24BF': 'J', + '\uFF2A': 'J', + '\u0134': 'J', + '\u0248': 'J', + '\u24C0': 'K', + '\uFF2B': 'K', + '\u1E30': 'K', + '\u01E8': 'K', + '\u1E32': 'K', + '\u0136': 'K', + '\u1E34': 'K', + '\u0198': 'K', + '\u2C69': 'K', + '\uA740': 'K', + '\uA742': 'K', + '\uA744': 'K', + '\uA7A2': 'K', + '\u24C1': 'L', + '\uFF2C': 'L', + '\u013F': 'L', + '\u0139': 'L', + '\u013D': 'L', + '\u1E36': 'L', + '\u1E38': 'L', + '\u013B': 'L', + '\u1E3C': 'L', + '\u1E3A': 'L', + '\u0141': 'L', + '\u023D': 'L', + '\u2C62': 'L', + '\u2C60': 'L', + '\uA748': 'L', + '\uA746': 'L', + '\uA780': 'L', + '\u01C7': 'LJ', + '\u01C8': 'Lj', + '\u24C2': 'M', + '\uFF2D': 'M', + '\u1E3E': 'M', + '\u1E40': 'M', + '\u1E42': 'M', + '\u2C6E': 'M', + '\u019C': 'M', + '\u24C3': 'N', + '\uFF2E': 'N', + '\u01F8': 'N', + '\u0143': 'N', + '\u00D1': 'N', + '\u1E44': 'N', + '\u0147': 'N', + '\u1E46': 'N', + '\u0145': 'N', + '\u1E4A': 'N', + '\u1E48': 'N', + '\u0220': 'N', + '\u019D': 'N', + '\uA790': 'N', + '\uA7A4': 'N', + '\u01CA': 'NJ', + '\u01CB': 'Nj', + '\u24C4': 'O', + '\uFF2F': 'O', + '\u00D2': 'O', + '\u00D3': 'O', + '\u00D4': 'O', + '\u1ED2': 'O', + '\u1ED0': 'O', + '\u1ED6': 'O', + '\u1ED4': 'O', + '\u00D5': 'O', + '\u1E4C': 'O', + '\u022C': 'O', + '\u1E4E': 'O', + '\u014C': 'O', + '\u1E50': 'O', + '\u1E52': 'O', + '\u014E': 'O', + '\u022E': 'O', + '\u0230': 'O', + '\u00D6': 'O', + '\u022A': 'O', + '\u1ECE': 'O', + '\u0150': 'O', + '\u01D1': 'O', + '\u020C': 'O', + '\u020E': 'O', + '\u01A0': 'O', + '\u1EDC': 'O', + '\u1EDA': 'O', + '\u1EE0': 'O', + '\u1EDE': 'O', + '\u1EE2': 'O', + '\u1ECC': 'O', + '\u1ED8': 'O', + '\u01EA': 'O', + '\u01EC': 'O', + '\u00D8': 'O', + '\u01FE': 'O', + '\u0186': 'O', + '\u019F': 'O', + '\uA74A': 'O', + '\uA74C': 'O', + '\u01A2': 'OI', + '\uA74E': 'OO', + '\u0222': 'OU', + '\u24C5': 'P', + '\uFF30': 'P', + '\u1E54': 'P', + '\u1E56': 'P', + '\u01A4': 'P', + '\u2C63': 'P', + '\uA750': 'P', + '\uA752': 'P', + '\uA754': 'P', + '\u24C6': 'Q', + '\uFF31': 'Q', + '\uA756': 'Q', + '\uA758': 'Q', + '\u024A': 'Q', + '\u24C7': 'R', + '\uFF32': 'R', + '\u0154': 'R', + '\u1E58': 'R', + '\u0158': 'R', + '\u0210': 'R', + '\u0212': 'R', + '\u1E5A': 'R', + '\u1E5C': 'R', + '\u0156': 'R', + '\u1E5E': 'R', + '\u024C': 'R', + '\u2C64': 'R', + '\uA75A': 'R', + '\uA7A6': 'R', + '\uA782': 'R', + '\u24C8': 'S', + '\uFF33': 'S', + '\u1E9E': 'S', + '\u015A': 'S', + '\u1E64': 'S', + '\u015C': 'S', + '\u1E60': 'S', + '\u0160': 'S', + '\u1E66': 'S', + '\u1E62': 'S', + '\u1E68': 'S', + '\u0218': 'S', + '\u015E': 'S', + '\u2C7E': 'S', + '\uA7A8': 'S', + '\uA784': 'S', + '\u24C9': 'T', + '\uFF34': 'T', + '\u1E6A': 'T', + '\u0164': 'T', + '\u1E6C': 'T', + '\u021A': 'T', + '\u0162': 'T', + '\u1E70': 'T', + '\u1E6E': 'T', + '\u0166': 'T', + '\u01AC': 'T', + '\u01AE': 'T', + '\u023E': 'T', + '\uA786': 'T', + '\uA728': 'TZ', + '\u24CA': 'U', + '\uFF35': 'U', + '\u00D9': 'U', + '\u00DA': 'U', + '\u00DB': 'U', + '\u0168': 'U', + '\u1E78': 'U', + '\u016A': 'U', + '\u1E7A': 'U', + '\u016C': 'U', + '\u00DC': 'U', + '\u01DB': 'U', + '\u01D7': 'U', + '\u01D5': 'U', + '\u01D9': 'U', + '\u1EE6': 'U', + '\u016E': 'U', + '\u0170': 'U', + '\u01D3': 'U', + '\u0214': 'U', + '\u0216': 'U', + '\u01AF': 'U', + '\u1EEA': 'U', + '\u1EE8': 'U', + '\u1EEE': 'U', + '\u1EEC': 'U', + '\u1EF0': 'U', + '\u1EE4': 'U', + '\u1E72': 'U', + '\u0172': 'U', + '\u1E76': 'U', + '\u1E74': 'U', + '\u0244': 'U', + '\u24CB': 'V', + '\uFF36': 'V', + '\u1E7C': 'V', + '\u1E7E': 'V', + '\u01B2': 'V', + '\uA75E': 'V', + '\u0245': 'V', + '\uA760': 'VY', + '\u24CC': 'W', + '\uFF37': 'W', + '\u1E80': 'W', + '\u1E82': 'W', + '\u0174': 'W', + '\u1E86': 'W', + '\u1E84': 'W', + '\u1E88': 'W', + '\u2C72': 'W', + '\u24CD': 'X', + '\uFF38': 'X', + '\u1E8A': 'X', + '\u1E8C': 'X', + '\u24CE': 'Y', + '\uFF39': 'Y', + '\u1EF2': 'Y', + '\u00DD': 'Y', + '\u0176': 'Y', + '\u1EF8': 'Y', + '\u0232': 'Y', + '\u1E8E': 'Y', + '\u0178': 'Y', + '\u1EF6': 'Y', + '\u1EF4': 'Y', + '\u01B3': 'Y', + '\u024E': 'Y', + '\u1EFE': 'Y', + '\u24CF': 'Z', + '\uFF3A': 'Z', + '\u0179': 'Z', + '\u1E90': 'Z', + '\u017B': 'Z', + '\u017D': 'Z', + '\u1E92': 'Z', + '\u1E94': 'Z', + '\u01B5': 'Z', + '\u0224': 'Z', + '\u2C7F': 'Z', + '\u2C6B': 'Z', + '\uA762': 'Z', + '\u24D0': 'a', + '\uFF41': 'a', + '\u1E9A': 'a', + '\u00E0': 'a', + '\u00E1': 'a', + '\u00E2': 'a', + '\u1EA7': 'a', + '\u1EA5': 'a', + '\u1EAB': 'a', + '\u1EA9': 'a', + '\u00E3': 'a', + '\u0101': 'a', + '\u0103': 'a', + '\u1EB1': 'a', + '\u1EAF': 'a', + '\u1EB5': 'a', + '\u1EB3': 'a', + '\u0227': 'a', + '\u01E1': 'a', + '\u00E4': 'a', + '\u01DF': 'a', + '\u1EA3': 'a', + '\u00E5': 'a', + '\u01FB': 'a', + '\u01CE': 'a', + '\u0201': 'a', + '\u0203': 'a', + '\u1EA1': 'a', + '\u1EAD': 'a', + '\u1EB7': 'a', + '\u1E01': 'a', + '\u0105': 'a', + '\u2C65': 'a', + '\u0250': 'a', + '\uA733': 'aa', + '\u00E6': 'ae', + '\u01FD': 'ae', + '\u01E3': 'ae', + '\uA735': 'ao', + '\uA737': 'au', + '\uA739': 'av', + '\uA73B': 'av', + '\uA73D': 'ay', + '\u24D1': 'b', + '\uFF42': 'b', + '\u1E03': 'b', + '\u1E05': 'b', + '\u1E07': 'b', + '\u0180': 'b', + '\u0183': 'b', + '\u0253': 'b', + '\u24D2': 'c', + '\uFF43': 'c', + '\u0107': 'c', + '\u0109': 'c', + '\u010B': 'c', + '\u010D': 'c', + '\u00E7': 'c', + '\u1E09': 'c', + '\u0188': 'c', + '\u023C': 'c', + '\uA73F': 'c', + '\u2184': 'c', + '\u24D3': 'd', + '\uFF44': 'd', + '\u1E0B': 'd', + '\u010F': 'd', + '\u1E0D': 'd', + '\u1E11': 'd', + '\u1E13': 'd', + '\u1E0F': 'd', + '\u0111': 'd', + '\u018C': 'd', + '\u0256': 'd', + '\u0257': 'd', + '\uA77A': 'd', + '\u01F3': 'dz', + '\u01C6': 'dz', + '\u24D4': 'e', + '\uFF45': 'e', + '\u00E8': 'e', + '\u00E9': 'e', + '\u00EA': 'e', + '\u1EC1': 'e', + '\u1EBF': 'e', + '\u1EC5': 'e', + '\u1EC3': 'e', + '\u1EBD': 'e', + '\u0113': 'e', + '\u1E15': 'e', + '\u1E17': 'e', + '\u0115': 'e', + '\u0117': 'e', + '\u00EB': 'e', + '\u1EBB': 'e', + '\u011B': 'e', + '\u0205': 'e', + '\u0207': 'e', + '\u1EB9': 'e', + '\u1EC7': 'e', + '\u0229': 'e', + '\u1E1D': 'e', + '\u0119': 'e', + '\u1E19': 'e', + '\u1E1B': 'e', + '\u0247': 'e', + '\u025B': 'e', + '\u01DD': 'e', + '\u24D5': 'f', + '\uFF46': 'f', + '\u1E1F': 'f', + '\u0192': 'f', + '\uA77C': 'f', + '\u24D6': 'g', + '\uFF47': 'g', + '\u01F5': 'g', + '\u011D': 'g', + '\u1E21': 'g', + '\u011F': 'g', + '\u0121': 'g', + '\u01E7': 'g', + '\u0123': 'g', + '\u01E5': 'g', + '\u0260': 'g', + '\uA7A1': 'g', + '\u1D79': 'g', + '\uA77F': 'g', + '\u24D7': 'h', + '\uFF48': 'h', + '\u0125': 'h', + '\u1E23': 'h', + '\u1E27': 'h', + '\u021F': 'h', + '\u1E25': 'h', + '\u1E29': 'h', + '\u1E2B': 'h', + '\u1E96': 'h', + '\u0127': 'h', + '\u2C68': 'h', + '\u2C76': 'h', + '\u0265': 'h', + '\u0195': 'hv', + '\u24D8': 'i', + '\uFF49': 'i', + '\u00EC': 'i', + '\u00ED': 'i', + '\u00EE': 'i', + '\u0129': 'i', + '\u012B': 'i', + '\u012D': 'i', + '\u00EF': 'i', + '\u1E2F': 'i', + '\u1EC9': 'i', + '\u01D0': 'i', + '\u0209': 'i', + '\u020B': 'i', + '\u1ECB': 'i', + '\u012F': 'i', + '\u1E2D': 'i', + '\u0268': 'i', + '\u0131': 'i', + '\u24D9': 'j', + '\uFF4A': 'j', + '\u0135': 'j', + '\u01F0': 'j', + '\u0249': 'j', + '\u24DA': 'k', + '\uFF4B': 'k', + '\u1E31': 'k', + '\u01E9': 'k', + '\u1E33': 'k', + '\u0137': 'k', + '\u1E35': 'k', + '\u0199': 'k', + '\u2C6A': 'k', + '\uA741': 'k', + '\uA743': 'k', + '\uA745': 'k', + '\uA7A3': 'k', + '\u24DB': 'l', + '\uFF4C': 'l', + '\u0140': 'l', + '\u013A': 'l', + '\u013E': 'l', + '\u1E37': 'l', + '\u1E39': 'l', + '\u013C': 'l', + '\u1E3D': 'l', + '\u1E3B': 'l', + '\u017F': 'l', + '\u0142': 'l', + '\u019A': 'l', + '\u026B': 'l', + '\u2C61': 'l', + '\uA749': 'l', + '\uA781': 'l', + '\uA747': 'l', + '\u01C9': 'lj', + '\u24DC': 'm', + '\uFF4D': 'm', + '\u1E3F': 'm', + '\u1E41': 'm', + '\u1E43': 'm', + '\u0271': 'm', + '\u026F': 'm', + '\u24DD': 'n', + '\uFF4E': 'n', + '\u01F9': 'n', + '\u0144': 'n', + '\u00F1': 'n', + '\u1E45': 'n', + '\u0148': 'n', + '\u1E47': 'n', + '\u0146': 'n', + '\u1E4B': 'n', + '\u1E49': 'n', + '\u019E': 'n', + '\u0272': 'n', + '\u0149': 'n', + '\uA791': 'n', + '\uA7A5': 'n', + '\u01CC': 'nj', + '\u24DE': 'o', + '\uFF4F': 'o', + '\u00F2': 'o', + '\u00F3': 'o', + '\u00F4': 'o', + '\u1ED3': 'o', + '\u1ED1': 'o', + '\u1ED7': 'o', + '\u1ED5': 'o', + '\u00F5': 'o', + '\u1E4D': 'o', + '\u022D': 'o', + '\u1E4F': 'o', + '\u014D': 'o', + '\u1E51': 'o', + '\u1E53': 'o', + '\u014F': 'o', + '\u022F': 'o', + '\u0231': 'o', + '\u00F6': 'o', + '\u022B': 'o', + '\u1ECF': 'o', + '\u0151': 'o', + '\u01D2': 'o', + '\u020D': 'o', + '\u020F': 'o', + '\u01A1': 'o', + '\u1EDD': 'o', + '\u1EDB': 'o', + '\u1EE1': 'o', + '\u1EDF': 'o', + '\u1EE3': 'o', + '\u1ECD': 'o', + '\u1ED9': 'o', + '\u01EB': 'o', + '\u01ED': 'o', + '\u00F8': 'o', + '\u01FF': 'o', + '\u0254': 'o', + '\uA74B': 'o', + '\uA74D': 'o', + '\u0275': 'o', + '\u01A3': 'oi', + '\u0223': 'ou', + '\uA74F': 'oo', + '\u24DF': 'p', + '\uFF50': 'p', + '\u1E55': 'p', + '\u1E57': 'p', + '\u01A5': 'p', + '\u1D7D': 'p', + '\uA751': 'p', + '\uA753': 'p', + '\uA755': 'p', + '\u24E0': 'q', + '\uFF51': 'q', + '\u024B': 'q', + '\uA757': 'q', + '\uA759': 'q', + '\u24E1': 'r', + '\uFF52': 'r', + '\u0155': 'r', + '\u1E59': 'r', + '\u0159': 'r', + '\u0211': 'r', + '\u0213': 'r', + '\u1E5B': 'r', + '\u1E5D': 'r', + '\u0157': 'r', + '\u1E5F': 'r', + '\u024D': 'r', + '\u027D': 'r', + '\uA75B': 'r', + '\uA7A7': 'r', + '\uA783': 'r', + '\u24E2': 's', + '\uFF53': 's', + '\u00DF': 's', + '\u015B': 's', + '\u1E65': 's', + '\u015D': 's', + '\u1E61': 's', + '\u0161': 's', + '\u1E67': 's', + '\u1E63': 's', + '\u1E69': 's', + '\u0219': 's', + '\u015F': 's', + '\u023F': 's', + '\uA7A9': 's', + '\uA785': 's', + '\u1E9B': 's', + '\u24E3': 't', + '\uFF54': 't', + '\u1E6B': 't', + '\u1E97': 't', + '\u0165': 't', + '\u1E6D': 't', + '\u021B': 't', + '\u0163': 't', + '\u1E71': 't', + '\u1E6F': 't', + '\u0167': 't', + '\u01AD': 't', + '\u0288': 't', + '\u2C66': 't', + '\uA787': 't', + '\uA729': 'tz', + '\u24E4': 'u', + '\uFF55': 'u', + '\u00F9': 'u', + '\u00FA': 'u', + '\u00FB': 'u', + '\u0169': 'u', + '\u1E79': 'u', + '\u016B': 'u', + '\u1E7B': 'u', + '\u016D': 'u', + '\u00FC': 'u', + '\u01DC': 'u', + '\u01D8': 'u', + '\u01D6': 'u', + '\u01DA': 'u', + '\u1EE7': 'u', + '\u016F': 'u', + '\u0171': 'u', + '\u01D4': 'u', + '\u0215': 'u', + '\u0217': 'u', + '\u01B0': 'u', + '\u1EEB': 'u', + '\u1EE9': 'u', + '\u1EEF': 'u', + '\u1EED': 'u', + '\u1EF1': 'u', + '\u1EE5': 'u', + '\u1E73': 'u', + '\u0173': 'u', + '\u1E77': 'u', + '\u1E75': 'u', + '\u0289': 'u', + '\u24E5': 'v', + '\uFF56': 'v', + '\u1E7D': 'v', + '\u1E7F': 'v', + '\u028B': 'v', + '\uA75F': 'v', + '\u028C': 'v', + '\uA761': 'vy', + '\u24E6': 'w', + '\uFF57': 'w', + '\u1E81': 'w', + '\u1E83': 'w', + '\u0175': 'w', + '\u1E87': 'w', + '\u1E85': 'w', + '\u1E98': 'w', + '\u1E89': 'w', + '\u2C73': 'w', + '\u24E7': 'x', + '\uFF58': 'x', + '\u1E8B': 'x', + '\u1E8D': 'x', + '\u24E8': 'y', + '\uFF59': 'y', + '\u1EF3': 'y', + '\u00FD': 'y', + '\u0177': 'y', + '\u1EF9': 'y', + '\u0233': 'y', + '\u1E8F': 'y', + '\u00FF': 'y', + '\u1EF7': 'y', + '\u1E99': 'y', + '\u1EF5': 'y', + '\u01B4': 'y', + '\u024F': 'y', + '\u1EFF': 'y', + '\u24E9': 'z', + '\uFF5A': 'z', + '\u017A': 'z', + '\u1E91': 'z', + '\u017C': 'z', + '\u017E': 'z', + '\u1E93': 'z', + '\u1E95': 'z', + '\u01B6': 'z', + '\u0225': 'z', + '\u0240': 'z', + '\u2C6C': 'z', + '\uA763': 'z', + '\u0386': '\u0391', + '\u0388': '\u0395', + '\u0389': '\u0397', + '\u038A': '\u0399', + '\u03AA': '\u0399', + '\u038C': '\u039F', + '\u038E': '\u03A5', + '\u03AB': '\u03A5', + '\u038F': '\u03A9', + '\u03AC': '\u03B1', + '\u03AD': '\u03B5', + '\u03AE': '\u03B7', + '\u03AF': '\u03B9', + '\u03CA': '\u03B9', + '\u0390': '\u03B9', + '\u03CC': '\u03BF', + '\u03CD': '\u03C5', + '\u03CB': '\u03C5', + '\u03B0': '\u03C5', + '\u03C9': '\u03C9', + '\u03C2': '\u03C3' + }; + + return diacritics; +}); + +S2.define('select2/data/base',[ + '../utils' +], function (Utils) { + function BaseAdapter ($element, options) { + BaseAdapter.__super__.constructor.call(this); + } + + Utils.Extend(BaseAdapter, Utils.Observable); + + BaseAdapter.prototype.current = function (callback) { + throw new Error('The `current` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.query = function (params, callback) { + throw new Error('The `query` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.bind = function (container, $container) { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.destroy = function () { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.generateResultId = function (container, data) { + var id = container.id + '-result-'; + + id += Utils.generateChars(4); + + if (data.id != null) { + id += '-' + data.id.toString(); + } else { + id += '-' + Utils.generateChars(4); + } + return id; + }; + + return BaseAdapter; +}); + +S2.define('select2/data/select',[ + './base', + '../utils', + 'jquery' +], function (BaseAdapter, Utils, $) { + function SelectAdapter ($element, options) { + this.$element = $element; + this.options = options; + + SelectAdapter.__super__.constructor.call(this); + } + + Utils.Extend(SelectAdapter, BaseAdapter); + + SelectAdapter.prototype.current = function (callback) { + var data = []; + var self = this; + + this.$element.find(':selected').each(function () { + var $option = $(this); + + var option = self.item($option); + + data.push(option); + }); + + callback(data); + }; + + SelectAdapter.prototype.select = function (data) { + var self = this; + + data.selected = true; + + // If data.element is a DOM node, use it instead + if ($(data.element).is('option')) { + data.element.selected = true; + + this.$element.trigger('change'); + + return; + } + + if (this.$element.prop('multiple')) { + this.current(function (currentData) { + var val = []; + + data = [data]; + data.push.apply(data, currentData); + + for (var d = 0; d < data.length; d++) { + var id = data[d].id; + + if ($.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + self.$element.trigger('change'); + }); + } else { + var val = data.id; + + this.$element.val(val); + this.$element.trigger('change'); + } + }; + + SelectAdapter.prototype.unselect = function (data) { + var self = this; + + if (!this.$element.prop('multiple')) { + return; + } + + data.selected = false; + + if ($(data.element).is('option')) { + data.element.selected = false; + + this.$element.trigger('change'); + + return; + } + + this.current(function (currentData) { + var val = []; + + for (var d = 0; d < currentData.length; d++) { + var id = currentData[d].id; + + if (id !== data.id && $.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + + self.$element.trigger('change'); + }); + }; + + SelectAdapter.prototype.bind = function (container, $container) { + var self = this; + + this.container = container; + + container.on('select', function (params) { + self.select(params.data); + }); + + container.on('unselect', function (params) { + self.unselect(params.data); + }); + }; + + SelectAdapter.prototype.destroy = function () { + // Remove anything added to child elements + this.$element.find('*').each(function () { + // Remove any custom data set by Select2 + $.removeData(this, 'data'); + }); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + var $options = this.$element.children(); + + $options.each(function () { + var $option = $(this); + + if (!$option.is('option') && !$option.is('optgroup')) { + return; + } + + var option = self.item($option); + + var matches = self.matches(params, option); + + if (matches !== null) { + data.push(matches); + } + }); + + callback({ + results: data + }); + }; + + SelectAdapter.prototype.addOptions = function ($options) { + Utils.appendMany(this.$element, $options); + }; + + SelectAdapter.prototype.option = function (data) { + var option; + + if (data.children) { + option = document.createElement('optgroup'); + option.label = data.text; + } else { + option = document.createElement('option'); + + if (option.textContent !== undefined) { + option.textContent = data.text; + } else { + option.innerText = data.text; + } + } + + if (data.id) { + option.value = data.id; + } + + if (data.disabled) { + option.disabled = true; + } + + if (data.selected) { + option.selected = true; + } + + if (data.title) { + option.title = data.title; + } + + var $option = $(option); + + var normalizedData = this._normalizeItem(data); + normalizedData.element = option; + + // Override the option's data with the combined data + $.data(option, 'data', normalizedData); + + return $option; + }; + + SelectAdapter.prototype.item = function ($option) { + var data = {}; + + data = $.data($option[0], 'data'); + + if (data != null) { + return data; + } + + if ($option.is('option')) { + data = { + id: $option.val(), + text: $option.text(), + disabled: $option.prop('disabled'), + selected: $option.prop('selected'), + title: $option.prop('title') + }; + } else if ($option.is('optgroup')) { + data = { + text: $option.prop('label'), + children: [], + title: $option.prop('title') + }; + + var $children = $option.children('option'); + var children = []; + + for (var c = 0; c < $children.length; c++) { + var $child = $($children[c]); + + var child = this.item($child); + + children.push(child); + } + + data.children = children; + } + + data = this._normalizeItem(data); + data.element = $option[0]; + + $.data($option[0], 'data', data); + + return data; + }; + + SelectAdapter.prototype._normalizeItem = function (item) { + if (!$.isPlainObject(item)) { + item = { + id: item, + text: item + }; + } + + item = $.extend({}, { + text: '' + }, item); + + var defaults = { + selected: false, + disabled: false + }; + + if (item.id != null) { + item.id = item.id.toString(); + } + + if (item.text != null) { + item.text = item.text.toString(); + } + + if (item._resultId == null && item.id && this.container != null) { + item._resultId = this.generateResultId(this.container, item); + } + + return $.extend({}, defaults, item); + }; + + SelectAdapter.prototype.matches = function (params, data) { + var matcher = this.options.get('matcher'); + + return matcher(params, data); + }; + + return SelectAdapter; +}); + +S2.define('select2/data/array',[ + './select', + '../utils', + 'jquery' +], function (SelectAdapter, Utils, $) { + function ArrayAdapter ($element, options) { + var data = options.get('data') || []; + + ArrayAdapter.__super__.constructor.call(this, $element, options); + + this.addOptions(this.convertToOptions(data)); + } + + Utils.Extend(ArrayAdapter, SelectAdapter); + + ArrayAdapter.prototype.select = function (data) { + var $option = this.$element.find('option').filter(function (i, elm) { + return elm.value == data.id.toString(); + }); + + if ($option.length === 0) { + $option = this.option(data); + + this.addOptions($option); + } + + ArrayAdapter.__super__.select.call(this, data); + }; + + ArrayAdapter.prototype.convertToOptions = function (data) { + var self = this; + + var $existing = this.$element.find('option'); + var existingIds = $existing.map(function () { + return self.item($(this)).id; + }).get(); + + var $options = []; + + // Filter out all items except for the one passed in the argument + function onlyItem (item) { + return function () { + return $(this).val() == item.id; + }; + } + + for (var d = 0; d < data.length; d++) { + var item = this._normalizeItem(data[d]); + + // Skip items which were pre-loaded, only merge the data + if ($.inArray(item.id, existingIds) >= 0) { + var $existingOption = $existing.filter(onlyItem(item)); + + var existingData = this.item($existingOption); + var newData = $.extend(true, {}, item, existingData); + + var $newOption = this.option(newData); + + $existingOption.replaceWith($newOption); + + continue; + } + + var $option = this.option(item); + + if (item.children) { + var $children = this.convertToOptions(item.children); + + Utils.appendMany($option, $children); + } + + $options.push($option); + } + + return $options; + }; + + return ArrayAdapter; +}); + +S2.define('select2/data/ajax',[ + './array', + '../utils', + 'jquery' +], function (ArrayAdapter, Utils, $) { + function AjaxAdapter ($element, options) { + this.ajaxOptions = this._applyDefaults(options.get('ajax')); + + if (this.ajaxOptions.processResults != null) { + this.processResults = this.ajaxOptions.processResults; + } + + AjaxAdapter.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(AjaxAdapter, ArrayAdapter); + + AjaxAdapter.prototype._applyDefaults = function (options) { + var defaults = { + data: function (params) { + return $.extend({}, params, { + q: params.term + }); + }, + transport: function (params, success, failure) { + var $request = $.ajax(params); + + $request.then(success); + $request.fail(failure); + + return $request; + } + }; + + return $.extend({}, defaults, options, true); + }; + + AjaxAdapter.prototype.processResults = function (results) { + return results; + }; + + AjaxAdapter.prototype.query = function (params, callback) { + var matches = []; + var self = this; + + if (this._request != null) { + // JSONP requests cannot always be aborted + if ($.isFunction(this._request.abort)) { + this._request.abort(); + } + + this._request = null; + } + + var options = $.extend({ + type: 'GET' + }, this.ajaxOptions); + + if (typeof options.url === 'function') { + options.url = options.url.call(this.$element, params); + } + + if (typeof options.data === 'function') { + options.data = options.data.call(this.$element, params); + } + + function request () { + var $request = options.transport(options, function (data) { + var results = self.processResults(data, params); + + if (self.options.get('debug') && window.console && console.error) { + // Check to make sure that the response included a `results` key. + if (!results || !results.results || !$.isArray(results.results)) { + console.error( + 'Select2: The AJAX results did not return an array in the ' + + '`results` key of the response.' + ); + } + } + + callback(results); + }, function () { + // Attempt to detect if a request was aborted + // Only works if the transport exposes a status property + if ($request.status && $request.status === '0') { + return; + } + + self.trigger('results:message', { + message: 'errorLoading' + }); + }); + + self._request = $request; + } + + if (this.ajaxOptions.delay && params.term != null) { + if (this._queryTimeout) { + window.clearTimeout(this._queryTimeout); + } + + this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); + } else { + request(); + } + }; + + return AjaxAdapter; +}); + +S2.define('select2/data/tags',[ + 'jquery' +], function ($) { + function Tags (decorated, $element, options) { + var tags = options.get('tags'); + + var createTag = options.get('createTag'); + + if (createTag !== undefined) { + this.createTag = createTag; + } + + var insertTag = options.get('insertTag'); + + if (insertTag !== undefined) { + this.insertTag = insertTag; + } + + decorated.call(this, $element, options); + + if ($.isArray(tags)) { + for (var t = 0; t < tags.length; t++) { + var tag = tags[t]; + var item = this._normalizeItem(tag); + + var $option = this.option(item); + + this.$element.append($option); + } + } + } + + Tags.prototype.query = function (decorated, params, callback) { + var self = this; + + this._removeOldTags(); + + if (params.term == null || params.page != null) { + decorated.call(this, params, callback); + return; + } + + function wrapper (obj, child) { + var data = obj.results; + + for (var i = 0; i < data.length; i++) { + var option = data[i]; + + var checkChildren = ( + option.children != null && + !wrapper({ + results: option.children + }, true) + ); + + var checkText = option.text === params.term; + + if (checkText || checkChildren) { + if (child) { + return false; + } + + obj.data = data; + callback(obj); + + return; + } + } + + if (child) { + return true; + } + + var tag = self.createTag(params); + + if (tag != null) { + var $option = self.option(tag); + $option.attr('data-select2-tag', true); + + self.addOptions([$option]); + + self.insertTag(data, tag); + } + + obj.results = data; + + callback(obj); + } + + decorated.call(this, params, wrapper); + }; + + Tags.prototype.createTag = function (decorated, params) { + var term = $.trim(params.term); + + if (term === '') { + return null; + } + + return { + id: term, + text: term + }; + }; + + Tags.prototype.insertTag = function (_, data, tag) { + data.unshift(tag); + }; + + Tags.prototype._removeOldTags = function (_) { + var tag = this._lastTag; + + var $options = this.$element.find('option[data-select2-tag]'); + + $options.each(function () { + if (this.selected) { + return; + } + + $(this).remove(); + }); + }; + + return Tags; +}); + +S2.define('select2/data/tokenizer',[ + 'jquery' +], function ($) { + function Tokenizer (decorated, $element, options) { + var tokenizer = options.get('tokenizer'); + + if (tokenizer !== undefined) { + this.tokenizer = tokenizer; + } + + decorated.call(this, $element, options); + } + + Tokenizer.prototype.bind = function (decorated, container, $container) { + decorated.call(this, container, $container); + + this.$search = container.dropdown.$search || container.selection.$search || + $container.find('.select2-search__field'); + }; + + Tokenizer.prototype.query = function (decorated, params, callback) { + var self = this; + + function createAndSelect (data) { + // Normalize the data object so we can use it for checks + var item = self._normalizeItem(data); + + // Check if the data object already exists as a tag + // Select it if it doesn't + var $existingOptions = self.$element.find('option').filter(function () { + return $(this).val() === item.id; + }); + + // If an existing option wasn't found for it, create the option + if (!$existingOptions.length) { + var $option = self.option(item); + $option.attr('data-select2-tag', true); + + self._removeOldTags(); + self.addOptions([$option]); + } + + // Select the item, now that we know there is an option for it + select(item); + } + + function select (data) { + self.trigger('select', { + data: data + }); + } + + params.term = params.term || ''; + + var tokenData = this.tokenizer(params, this.options, createAndSelect); + + if (tokenData.term !== params.term) { + // Replace the search term if we have the search box + if (this.$search.length) { + this.$search.val(tokenData.term); + this.$search.focus(); + } + + params.term = tokenData.term; + } + + decorated.call(this, params, callback); + }; + + Tokenizer.prototype.tokenizer = function (_, params, options, callback) { + var separators = options.get('tokenSeparators') || []; + var term = params.term; + var i = 0; + + var createTag = this.createTag || function (params) { + return { + id: params.term, + text: params.term + }; + }; + + while (i < term.length) { + var termChar = term[i]; + + if ($.inArray(termChar, separators) === -1) { + i++; + + continue; + } + + var part = term.substr(0, i); + var partParams = $.extend({}, params, { + term: part + }); + + var data = createTag(partParams); + + if (data == null) { + i++; + continue; + } + + callback(data); + + // Reset the term to not include the tokenized portion + term = term.substr(i + 1) || ''; + i = 0; + } + + return { + term: term + }; + }; + + return Tokenizer; +}); + +S2.define('select2/data/minimumInputLength',[ + +], function () { + function MinimumInputLength (decorated, $e, options) { + this.minimumInputLength = options.get('minimumInputLength'); + + decorated.call(this, $e, options); + } + + MinimumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (params.term.length < this.minimumInputLength) { + this.trigger('results:message', { + message: 'inputTooShort', + args: { + minimum: this.minimumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MinimumInputLength; +}); + +S2.define('select2/data/maximumInputLength',[ + +], function () { + function MaximumInputLength (decorated, $e, options) { + this.maximumInputLength = options.get('maximumInputLength'); + + decorated.call(this, $e, options); + } + + MaximumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (this.maximumInputLength > 0 && + params.term.length > this.maximumInputLength) { + this.trigger('results:message', { + message: 'inputTooLong', + args: { + maximum: this.maximumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MaximumInputLength; +}); + +S2.define('select2/data/maximumSelectionLength',[ + +], function (){ + function MaximumSelectionLength (decorated, $e, options) { + this.maximumSelectionLength = options.get('maximumSelectionLength'); + + decorated.call(this, $e, options); + } + + MaximumSelectionLength.prototype.query = + function (decorated, params, callback) { + var self = this; + + this.current(function (currentData) { + var count = currentData != null ? currentData.length : 0; + if (self.maximumSelectionLength > 0 && + count >= self.maximumSelectionLength) { + self.trigger('results:message', { + message: 'maximumSelected', + args: { + maximum: self.maximumSelectionLength + } + }); + return; + } + decorated.call(self, params, callback); + }); + }; + + return MaximumSelectionLength; +}); + +S2.define('select2/dropdown',[ + 'jquery', + './utils' +], function ($, Utils) { + function Dropdown ($element, options) { + this.$element = $element; + this.options = options; + + Dropdown.__super__.constructor.call(this); + } + + Utils.Extend(Dropdown, Utils.Observable); + + Dropdown.prototype.render = function () { + var $dropdown = $( + '' + + '' + + '' + ); + + $dropdown.attr('dir', this.options.get('dir')); + + this.$dropdown = $dropdown; + + return $dropdown; + }; + + Dropdown.prototype.bind = function () { + // Should be implemented in subclasses + }; + + Dropdown.prototype.position = function ($dropdown, $container) { + // Should be implmented in subclasses + }; + + Dropdown.prototype.destroy = function () { + // Remove the dropdown from the DOM + this.$dropdown.remove(); + }; + + return Dropdown; +}); + +S2.define('select2/dropdown/search',[ + 'jquery', + '../utils' +], function ($, Utils) { + function Search () { } + + Search.prototype.render = function (decorated) { + var $rendered = decorated.call(this); + + var $search = $( + '' + + '' + + '' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + $rendered.prepend($search); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + this.$search.on('keydown', function (evt) { + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + }); + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$search.on('input', function (evt) { + // Unbind the duplicated `keyup` event + $(this).off('keyup'); + }); + + this.$search.on('keyup input', function (evt) { + self.handleSearch(evt); + }); + + container.on('open', function () { + self.$search.attr('tabindex', 0); + + self.$search.focus(); + + window.setTimeout(function () { + self.$search.focus(); + }, 0); + }); + + container.on('close', function () { + self.$search.attr('tabindex', -1); + + self.$search.val(''); + }); + + container.on('focus', function () { + if (container.isOpen()) { + self.$search.focus(); + } + }); + + container.on('results:all', function (params) { + if (params.query.term == null || params.query.term === '') { + var showSearch = self.showSearch(params); + + if (showSearch) { + self.$searchContainer.removeClass('select2-search--hide'); + } else { + self.$searchContainer.addClass('select2-search--hide'); + } + } + }); + }; + + Search.prototype.handleSearch = function (evt) { + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.showSearch = function (_, params) { + return true; + }; + + return Search; +}); + +S2.define('select2/dropdown/hidePlaceholder',[ + +], function () { + function HidePlaceholder (decorated, $element, options, dataAdapter) { + this.placeholder = this.normalizePlaceholder(options.get('placeholder')); + + decorated.call(this, $element, options, dataAdapter); + } + + HidePlaceholder.prototype.append = function (decorated, data) { + data.results = this.removePlaceholder(data.results); + + decorated.call(this, data); + }; + + HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { + if (typeof placeholder === 'string') { + placeholder = { + id: '', + text: placeholder + }; + } + + return placeholder; + }; + + HidePlaceholder.prototype.removePlaceholder = function (_, data) { + var modifiedData = data.slice(0); + + for (var d = data.length - 1; d >= 0; d--) { + var item = data[d]; + + if (this.placeholder.id === item.id) { + modifiedData.splice(d, 1); + } + } + + return modifiedData; + }; + + return HidePlaceholder; +}); + +S2.define('select2/dropdown/infiniteScroll',[ + 'jquery' +], function ($) { + function InfiniteScroll (decorated, $element, options, dataAdapter) { + this.lastParams = {}; + + decorated.call(this, $element, options, dataAdapter); + + this.$loadingMore = this.createLoadingMore(); + this.loading = false; + } + + InfiniteScroll.prototype.append = function (decorated, data) { + this.$loadingMore.remove(); + this.loading = false; + + decorated.call(this, data); + + if (this.showLoadingMore(data)) { + this.$results.append(this.$loadingMore); + } + }; + + InfiniteScroll.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('query', function (params) { + self.lastParams = params; + self.loading = true; + }); + + container.on('query:append', function (params) { + self.lastParams = params; + self.loading = true; + }); + + this.$results.on('scroll', function () { + var isLoadMoreVisible = $.contains( + document.documentElement, + self.$loadingMore[0] + ); + + if (self.loading || !isLoadMoreVisible) { + return; + } + + var currentOffset = self.$results.offset().top + + self.$results.outerHeight(false); + var loadingMoreOffset = self.$loadingMore.offset().top + + self.$loadingMore.outerHeight(false); + + if (currentOffset + 50 >= loadingMoreOffset) { + self.loadMore(); + } + }); + }; + + InfiniteScroll.prototype.loadMore = function () { + this.loading = true; + + var params = $.extend({}, {page: 1}, this.lastParams); + + params.page++; + + this.trigger('query:append', params); + }; + + InfiniteScroll.prototype.showLoadingMore = function (_, data) { + return data.pagination && data.pagination.more; + }; + + InfiniteScroll.prototype.createLoadingMore = function () { + var $option = $( + '
      • ' + ); + + var message = this.options.get('translations').get('loadingMore'); + + $option.html(message(this.lastParams)); + + return $option; + }; + + return InfiniteScroll; +}); + +S2.define('select2/dropdown/attachBody',[ + 'jquery', + '../utils' +], function ($, Utils) { + function AttachBody (decorated, $element, options) { + this.$dropdownParent = options.get('dropdownParent') || $(document.body); + + decorated.call(this, $element, options); + } + + AttachBody.prototype.bind = function (decorated, container, $container) { + var self = this; + + var setupResultsEvents = false; + + decorated.call(this, container, $container); + + container.on('open', function () { + self._showDropdown(); + self._attachPositioningHandler(container); + + if (!setupResultsEvents) { + setupResultsEvents = true; + + container.on('results:all', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('results:append', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + } + }); + + container.on('close', function () { + self._hideDropdown(); + self._detachPositioningHandler(container); + }); + + this.$dropdownContainer.on('mousedown', function (evt) { + evt.stopPropagation(); + }); + }; + + AttachBody.prototype.destroy = function (decorated) { + decorated.call(this); + + this.$dropdownContainer.remove(); + }; + + AttachBody.prototype.position = function (decorated, $dropdown, $container) { + // Clone all of the container classes + $dropdown.attr('class', $container.attr('class')); + + $dropdown.removeClass('select2'); + $dropdown.addClass('select2-container--open'); + + $dropdown.css({ + position: 'absolute', + top: -999999 + }); + + this.$container = $container; + }; + + AttachBody.prototype.render = function (decorated) { + var $container = $(''); + + var $dropdown = decorated.call(this); + $container.append($dropdown); + + this.$dropdownContainer = $container; + + return $container; + }; + + AttachBody.prototype._hideDropdown = function (decorated) { + this.$dropdownContainer.detach(); + }; + + AttachBody.prototype._attachPositioningHandler = + function (decorated, container) { + var self = this; + + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.each(function () { + $(this).data('select2-scroll-position', { + x: $(this).scrollLeft(), + y: $(this).scrollTop() + }); + }); + + $watchers.on(scrollEvent, function (ev) { + var position = $(this).data('select2-scroll-position'); + $(this).scrollTop(position.y); + }); + + $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, + function (e) { + self._positionDropdown(); + self._resizeDropdown(); + }); + }; + + AttachBody.prototype._detachPositioningHandler = + function (decorated, container) { + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.off(scrollEvent); + + $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); + }; + + AttachBody.prototype._positionDropdown = function () { + var $window = $(window); + + var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above'); + var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below'); + + var newDirection = null; + + var offset = this.$container.offset(); + + offset.bottom = offset.top + this.$container.outerHeight(false); + + var container = { + height: this.$container.outerHeight(false) + }; + + container.top = offset.top; + container.bottom = offset.top + container.height; + + var dropdown = { + height: this.$dropdown.outerHeight(false) + }; + + var viewport = { + top: $window.scrollTop(), + bottom: $window.scrollTop() + $window.height() + }; + + var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); + var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); + + var css = { + left: offset.left, + top: container.bottom + }; + + // Determine what the parent element is to use for calciulating the offset + var $offsetParent = this.$dropdownParent; + + // For statically positoned elements, we need to get the element + // that is determining the offset + if ($offsetParent.css('position') === 'static') { + $offsetParent = $offsetParent.offsetParent(); + } + + var parentOffset = $offsetParent.offset(); + + css.top -= parentOffset.top; + css.left -= parentOffset.left; + + if (!isCurrentlyAbove && !isCurrentlyBelow) { + newDirection = 'below'; + } + + if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { + newDirection = 'above'; + } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { + newDirection = 'below'; + } + + if (newDirection == 'above' || + (isCurrentlyAbove && newDirection !== 'below')) { + css.top = container.top - parentOffset.top - dropdown.height; + } + + if (newDirection != null) { + this.$dropdown + .removeClass('select2-dropdown--below select2-dropdown--above') + .addClass('select2-dropdown--' + newDirection); + this.$container + .removeClass('select2-container--below select2-container--above') + .addClass('select2-container--' + newDirection); + } + + this.$dropdownContainer.css(css); + }; + + AttachBody.prototype._resizeDropdown = function () { + var css = { + width: this.$container.outerWidth(false) + 'px' + }; + + if (this.options.get('dropdownAutoWidth')) { + css.minWidth = css.width; + css.position = 'relative'; + css.width = 'auto'; + } + + this.$dropdown.css(css); + }; + + AttachBody.prototype._showDropdown = function (decorated) { + this.$dropdownContainer.appendTo(this.$dropdownParent); + + this._positionDropdown(); + this._resizeDropdown(); + }; + + return AttachBody; +}); + +S2.define('select2/dropdown/minimumResultsForSearch',[ + +], function () { + function countResults (data) { + var count = 0; + + for (var d = 0; d < data.length; d++) { + var item = data[d]; + + if (item.children) { + count += countResults(item.children); + } else { + count++; + } + } + + return count; + } + + function MinimumResultsForSearch (decorated, $element, options, dataAdapter) { + this.minimumResultsForSearch = options.get('minimumResultsForSearch'); + + if (this.minimumResultsForSearch < 0) { + this.minimumResultsForSearch = Infinity; + } + + decorated.call(this, $element, options, dataAdapter); + } + + MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { + if (countResults(params.data.results) < this.minimumResultsForSearch) { + return false; + } + + return decorated.call(this, params); + }; + + return MinimumResultsForSearch; +}); + +S2.define('select2/dropdown/selectOnClose',[ + +], function () { + function SelectOnClose () { } + + SelectOnClose.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('close', function (params) { + self._handleSelectOnClose(params); + }); + }; + + SelectOnClose.prototype._handleSelectOnClose = function (_, params) { + if (params && params.originalSelect2Event != null) { + var event = params.originalSelect2Event; + + // Don't select an item if the close event was triggered from a select or + // unselect event + if (event._type === 'select' || event._type === 'unselect') { + return; + } + } + + var $highlightedResults = this.getHighlightedResults(); + + // Only select highlighted results + if ($highlightedResults.length < 1) { + return; + } + + var data = $highlightedResults.data('data'); + + // Don't re-select already selected resulte + if ( + (data.element != null && data.element.selected) || + (data.element == null && data.selected) + ) { + return; + } + + this.trigger('select', { + data: data + }); + }; + + return SelectOnClose; +}); + +S2.define('select2/dropdown/closeOnSelect',[ + +], function () { + function CloseOnSelect () { } + + CloseOnSelect.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('select', function (evt) { + self._selectTriggered(evt); + }); + + container.on('unselect', function (evt) { + self._selectTriggered(evt); + }); + }; + + CloseOnSelect.prototype._selectTriggered = function (_, evt) { + var originalEvent = evt.originalEvent; + + // Don't close if the control key is being held + if (originalEvent && originalEvent.ctrlKey) { + return; + } + + this.trigger('close', { + originalEvent: originalEvent, + originalSelect2Event: evt + }); + }; + + return CloseOnSelect; +}); + +S2.define('select2/i18n/en',[],function () { + // English + return { + errorLoading: function () { + return 'The results could not be loaded.'; + }, + inputTooLong: function (args) { + var overChars = args.input.length - args.maximum; + + var message = 'Please delete ' + overChars + ' character'; + + if (overChars != 1) { + message += 's'; + } + + return message; + }, + inputTooShort: function (args) { + var remainingChars = args.minimum - args.input.length; + + var message = 'Please enter ' + remainingChars + ' or more characters'; + + return message; + }, + loadingMore: function () { + return 'Loading more results…'; + }, + maximumSelected: function (args) { + var message = 'You can only select ' + args.maximum + ' item'; + + if (args.maximum != 1) { + message += 's'; + } + + return message; + }, + noResults: function () { + return 'No results found'; + }, + searching: function () { + return 'Searching…'; + } + }; +}); + +S2.define('select2/defaults',[ + 'jquery', + 'require', + + './results', + + './selection/single', + './selection/multiple', + './selection/placeholder', + './selection/allowClear', + './selection/search', + './selection/eventRelay', + + './utils', + './translation', + './diacritics', + + './data/select', + './data/array', + './data/ajax', + './data/tags', + './data/tokenizer', + './data/minimumInputLength', + './data/maximumInputLength', + './data/maximumSelectionLength', + + './dropdown', + './dropdown/search', + './dropdown/hidePlaceholder', + './dropdown/infiniteScroll', + './dropdown/attachBody', + './dropdown/minimumResultsForSearch', + './dropdown/selectOnClose', + './dropdown/closeOnSelect', + + './i18n/en' +], function ($, require, + + ResultsList, + + SingleSelection, MultipleSelection, Placeholder, AllowClear, + SelectionSearch, EventRelay, + + Utils, Translation, DIACRITICS, + + SelectData, ArrayData, AjaxData, Tags, Tokenizer, + MinimumInputLength, MaximumInputLength, MaximumSelectionLength, + + Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, + AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, + + EnglishTranslation) { + function Defaults () { + this.reset(); + } + + Defaults.prototype.apply = function (options) { + options = $.extend(true, {}, this.defaults, options); + + if (options.dataAdapter == null) { + if (options.ajax != null) { + options.dataAdapter = AjaxData; + } else if (options.data != null) { + options.dataAdapter = ArrayData; + } else { + options.dataAdapter = SelectData; + } + + if (options.minimumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MinimumInputLength + ); + } + + if (options.maximumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumInputLength + ); + } + + if (options.maximumSelectionLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumSelectionLength + ); + } + + if (options.tags) { + options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); + } + + if (options.tokenSeparators != null || options.tokenizer != null) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Tokenizer + ); + } + + if (options.query != null) { + var Query = require(options.amdBase + 'compat/query'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Query + ); + } + + if (options.initSelection != null) { + var InitSelection = require(options.amdBase + 'compat/initSelection'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + InitSelection + ); + } + } + + if (options.resultsAdapter == null) { + options.resultsAdapter = ResultsList; + + if (options.ajax != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + InfiniteScroll + ); + } + + if (options.placeholder != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + HidePlaceholder + ); + } + + if (options.selectOnClose) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + SelectOnClose + ); + } + } + + if (options.dropdownAdapter == null) { + if (options.multiple) { + options.dropdownAdapter = Dropdown; + } else { + var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); + + options.dropdownAdapter = SearchableDropdown; + } + + if (options.minimumResultsForSearch !== 0) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + MinimumResultsForSearch + ); + } + + if (options.closeOnSelect) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + CloseOnSelect + ); + } + + if ( + options.dropdownCssClass != null || + options.dropdownCss != null || + options.adaptDropdownCssClass != null + ) { + var DropdownCSS = require(options.amdBase + 'compat/dropdownCss'); + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + DropdownCSS + ); + } + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + AttachBody + ); + } + + if (options.selectionAdapter == null) { + if (options.multiple) { + options.selectionAdapter = MultipleSelection; + } else { + options.selectionAdapter = SingleSelection; + } + + // Add the placeholder mixin if a placeholder was specified + if (options.placeholder != null) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + Placeholder + ); + } + + if (options.allowClear) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + AllowClear + ); + } + + if (options.multiple) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + SelectionSearch + ); + } + + if ( + options.containerCssClass != null || + options.containerCss != null || + options.adaptContainerCssClass != null + ) { + var ContainerCSS = require(options.amdBase + 'compat/containerCss'); + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + ContainerCSS + ); + } + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + EventRelay + ); + } + + if (typeof options.language === 'string') { + // Check if the language is specified with a region + if (options.language.indexOf('-') > 0) { + // Extract the region information if it is included + var languageParts = options.language.split('-'); + var baseLanguage = languageParts[0]; + + options.language = [options.language, baseLanguage]; + } else { + options.language = [options.language]; + } + } + + if ($.isArray(options.language)) { + var languages = new Translation(); + options.language.push('en'); + + var languageNames = options.language; + + for (var l = 0; l < languageNames.length; l++) { + var name = languageNames[l]; + var language = {}; + + try { + // Try to load it with the original name + language = Translation.loadPath(name); + } catch (e) { + try { + // If we couldn't load it, check if it wasn't the full path + name = this.defaults.amdLanguageBase + name; + language = Translation.loadPath(name); + } catch (ex) { + // The translation could not be loaded at all. Sometimes this is + // because of a configuration problem, other times this can be + // because of how Select2 helps load all possible translation files. + if (options.debug && window.console && console.warn) { + console.warn( + 'Select2: The language file for "' + name + '" could not be ' + + 'automatically loaded. A fallback will be used instead.' + ); + } + + continue; + } + } + + languages.extend(language); + } + + options.translations = languages; + } else { + var baseTranslation = Translation.loadPath( + this.defaults.amdLanguageBase + 'en' + ); + var customTranslation = new Translation(options.language); + + customTranslation.extend(baseTranslation); + + options.translations = customTranslation; + } + + return options; + }; + + Defaults.prototype.reset = function () { + function stripDiacritics (text) { + // Used 'uni range + named function' from http://jsperf.com/diacritics/18 + function match(a) { + return DIACRITICS[a] || a; + } + + return text.replace(/[^\u0000-\u007E]/g, match); + } + + function matcher (params, data) { + // Always return the object if there is nothing to compare + if ($.trim(params.term) === '') { + return data; + } + + // Do a recursive check for options with children + if (data.children && data.children.length > 0) { + // Clone the data object if there are children + // This is required as we modify the object to remove any non-matches + var match = $.extend(true, {}, data); + + // Check each child of the option + for (var c = data.children.length - 1; c >= 0; c--) { + var child = data.children[c]; + + var matches = matcher(params, child); + + // If there wasn't a match, remove the object in the array + if (matches == null) { + match.children.splice(c, 1); + } + } + + // If any children matched, return the new object + if (match.children.length > 0) { + return match; + } + + // If there were no matching children, check just the plain object + return matcher(params, match); + } + + var original = stripDiacritics(data.text).toUpperCase(); + var term = stripDiacritics(params.term).toUpperCase(); + + // Check if the text contains the term + if (original.indexOf(term) > -1) { + return data; + } + + // If it doesn't contain the term, don't return anything + return null; + } + + this.defaults = { + amdBase: './', + amdLanguageBase: './i18n/', + closeOnSelect: true, + debug: false, + dropdownAutoWidth: false, + escapeMarkup: Utils.escapeMarkup, + language: EnglishTranslation, + matcher: matcher, + minimumInputLength: 0, + maximumInputLength: 0, + maximumSelectionLength: 0, + minimumResultsForSearch: 0, + selectOnClose: false, + sorter: function (data) { + return data; + }, + templateResult: function (result) { + return result.text; + }, + templateSelection: function (selection) { + return selection.text; + }, + theme: 'default', + width: 'resolve' + }; + }; + + Defaults.prototype.set = function (key, value) { + var camelKey = $.camelCase(key); + + var data = {}; + data[camelKey] = value; + + var convertedData = Utils._convertData(data); + + $.extend(this.defaults, convertedData); + }; + + var defaults = new Defaults(); + + return defaults; +}); + +S2.define('select2/options',[ + 'require', + 'jquery', + './defaults', + './utils' +], function (require, $, Defaults, Utils) { + function Options (options, $element) { + this.options = options; + + if ($element != null) { + this.fromElement($element); + } + + this.options = Defaults.apply(this.options); + + if ($element && $element.is('input')) { + var InputCompat = require(this.get('amdBase') + 'compat/inputData'); + + this.options.dataAdapter = Utils.Decorate( + this.options.dataAdapter, + InputCompat + ); + } + } + + Options.prototype.fromElement = function ($e) { + var excludedData = ['select2']; + + if (this.options.multiple == null) { + this.options.multiple = $e.prop('multiple'); + } + + if (this.options.disabled == null) { + this.options.disabled = $e.prop('disabled'); + } + + if (this.options.language == null) { + if ($e.prop('lang')) { + this.options.language = $e.prop('lang').toLowerCase(); + } else if ($e.closest('[lang]').prop('lang')) { + this.options.language = $e.closest('[lang]').prop('lang'); + } + } + + if (this.options.dir == null) { + if ($e.prop('dir')) { + this.options.dir = $e.prop('dir'); + } else if ($e.closest('[dir]').prop('dir')) { + this.options.dir = $e.closest('[dir]').prop('dir'); + } else { + this.options.dir = 'ltr'; + } + } + + $e.prop('disabled', this.options.disabled); + $e.prop('multiple', this.options.multiple); + + if ($e.data('select2Tags')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-select2-tags` attribute has been changed to ' + + 'use the `data-data` and `data-tags="true"` attributes and will be ' + + 'removed in future versions of Select2.' + ); + } + + $e.data('data', $e.data('select2Tags')); + $e.data('tags', true); + } + + if ($e.data('ajaxUrl')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-ajax-url` attribute has been changed to ' + + '`data-ajax--url` and support for the old attribute will be removed' + + ' in future versions of Select2.' + ); + } + + $e.attr('ajax--url', $e.data('ajaxUrl')); + $e.data('ajax--url', $e.data('ajaxUrl')); + } + + var dataset = {}; + + // Prefer the element's `dataset` attribute if it exists + // jQuery 1.x does not correctly handle data attributes with multiple dashes + if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { + dataset = $.extend(true, {}, $e[0].dataset, $e.data()); + } else { + dataset = $e.data(); + } + + var data = $.extend(true, {}, dataset); + + data = Utils._convertData(data); + + for (var key in data) { + if ($.inArray(key, excludedData) > -1) { + continue; + } + + if ($.isPlainObject(this.options[key])) { + $.extend(this.options[key], data[key]); + } else { + this.options[key] = data[key]; + } + } + + return this; + }; + + Options.prototype.get = function (key) { + return this.options[key]; + }; + + Options.prototype.set = function (key, val) { + this.options[key] = val; + }; + + return Options; +}); + +S2.define('select2/core',[ + 'jquery', + './options', + './utils', + './keys' +], function ($, Options, Utils, KEYS) { + var Select2 = function ($element, options) { + if ($element.data('select2') != null) { + $element.data('select2').destroy(); + } + + this.$element = $element; + + this.id = this._generateId($element); + + options = options || {}; + + this.options = new Options(options, $element); + + Select2.__super__.constructor.call(this); + + // Set up the tabindex + + var tabindex = $element.attr('tabindex') || 0; + $element.data('old-tabindex', tabindex); + $element.attr('tabindex', '-1'); + + // Set up containers and adapters + + var DataAdapter = this.options.get('dataAdapter'); + this.dataAdapter = new DataAdapter($element, this.options); + + var $container = this.render(); + + this._placeContainer($container); + + var SelectionAdapter = this.options.get('selectionAdapter'); + this.selection = new SelectionAdapter($element, this.options); + this.$selection = this.selection.render(); + + this.selection.position(this.$selection, $container); + + var DropdownAdapter = this.options.get('dropdownAdapter'); + this.dropdown = new DropdownAdapter($element, this.options); + this.$dropdown = this.dropdown.render(); + + this.dropdown.position(this.$dropdown, $container); + + var ResultsAdapter = this.options.get('resultsAdapter'); + this.results = new ResultsAdapter($element, this.options, this.dataAdapter); + this.$results = this.results.render(); + + this.results.position(this.$results, this.$dropdown); + + // Bind events + + var self = this; + + // Bind the container to all of the adapters + this._bindAdapters(); + + // Register any DOM event handlers + this._registerDomEvents(); + + // Register any internal event handlers + this._registerDataEvents(); + this._registerSelectionEvents(); + this._registerDropdownEvents(); + this._registerResultsEvents(); + this._registerEvents(); + + // Set the initial state + this.dataAdapter.current(function (initialData) { + self.trigger('selection:update', { + data: initialData + }); + }); + + // Hide the original select + $element.addClass('select2-hidden-accessible'); + $element.attr('aria-hidden', 'true'); + + // Synchronize any monitored attributes + this._syncAttributes(); + + $element.data('select2', this); + }; + + Utils.Extend(Select2, Utils.Observable); + + Select2.prototype._generateId = function ($element) { + var id = ''; + + if ($element.attr('id') != null) { + id = $element.attr('id'); + } else if ($element.attr('name') != null) { + id = $element.attr('name') + '-' + Utils.generateChars(2); + } else { + id = Utils.generateChars(4); + } + + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = 'select2-' + id; + + return id; + }; + + Select2.prototype._placeContainer = function ($container) { + $container.insertAfter(this.$element); + + var width = this._resolveWidth(this.$element, this.options.get('width')); + + if (width != null) { + $container.css('width', width); + } + }; + + Select2.prototype._resolveWidth = function ($element, method) { + var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; + + if (method == 'resolve') { + var styleWidth = this._resolveWidth($element, 'style'); + + if (styleWidth != null) { + return styleWidth; + } + + return this._resolveWidth($element, 'element'); + } + + if (method == 'element') { + var elementWidth = $element.outerWidth(false); + + if (elementWidth <= 0) { + return 'auto'; + } + + return elementWidth + 'px'; + } + + if (method == 'style') { + var style = $element.attr('style'); + + if (typeof(style) !== 'string') { + return null; + } + + var attrs = style.split(';'); + + for (var i = 0, l = attrs.length; i < l; i = i + 1) { + var attr = attrs[i].replace(/\s/g, ''); + var matches = attr.match(WIDTH); + + if (matches !== null && matches.length >= 1) { + return matches[1]; + } + } + + return null; + } + + return method; + }; + + Select2.prototype._bindAdapters = function () { + this.dataAdapter.bind(this, this.$container); + this.selection.bind(this, this.$container); + + this.dropdown.bind(this, this.$container); + this.results.bind(this, this.$container); + }; + + Select2.prototype._registerDomEvents = function () { + var self = this; + + this.$element.on('change.select2', function () { + self.dataAdapter.current(function (data) { + self.trigger('selection:update', { + data: data + }); + }); + }); + + this.$element.on('focus.select2', function (evt) { + self.trigger('focus', evt); + }); + + this._syncA = Utils.bind(this._syncAttributes, this); + this._syncS = Utils.bind(this._syncSubtree, this); + + if (this.$element[0].attachEvent) { + this.$element[0].attachEvent('onpropertychange', this._syncA); + } + + var observer = window.MutationObserver || + window.WebKitMutationObserver || + window.MozMutationObserver + ; + + if (observer != null) { + this._observer = new observer(function (mutations) { + $.each(mutations, self._syncA); + $.each(mutations, self._syncS); + }); + this._observer.observe(this.$element[0], { + attributes: true, + childList: true, + subtree: false + }); + } else if (this.$element[0].addEventListener) { + this.$element[0].addEventListener( + 'DOMAttrModified', + self._syncA, + false + ); + this.$element[0].addEventListener( + 'DOMNodeInserted', + self._syncS, + false + ); + this.$element[0].addEventListener( + 'DOMNodeRemoved', + self._syncS, + false + ); + } + }; + + Select2.prototype._registerDataEvents = function () { + var self = this; + + this.dataAdapter.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerSelectionEvents = function () { + var self = this; + var nonRelayEvents = ['toggle', 'focus']; + + this.selection.on('toggle', function () { + self.toggleDropdown(); + }); + + this.selection.on('focus', function (params) { + self.focus(params); + }); + + this.selection.on('*', function (name, params) { + if ($.inArray(name, nonRelayEvents) !== -1) { + return; + } + + self.trigger(name, params); + }); + }; + + Select2.prototype._registerDropdownEvents = function () { + var self = this; + + this.dropdown.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerResultsEvents = function () { + var self = this; + + this.results.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerEvents = function () { + var self = this; + + this.on('open', function () { + self.$container.addClass('select2-container--open'); + }); + + this.on('close', function () { + self.$container.removeClass('select2-container--open'); + }); + + this.on('enable', function () { + self.$container.removeClass('select2-container--disabled'); + }); + + this.on('disable', function () { + self.$container.addClass('select2-container--disabled'); + }); + + this.on('blur', function () { + self.$container.removeClass('select2-container--focus'); + }); + + this.on('query', function (params) { + if (!self.isOpen()) { + self.trigger('open', {}); + } + + this.dataAdapter.query(params, function (data) { + self.trigger('results:all', { + data: data, + query: params + }); + }); + }); + + this.on('query:append', function (params) { + this.dataAdapter.query(params, function (data) { + self.trigger('results:append', { + data: data, + query: params + }); + }); + }); + + this.on('keypress', function (evt) { + var key = evt.which; + + if (self.isOpen()) { + if (key === KEYS.ESC || key === KEYS.TAB || + (key === KEYS.UP && evt.altKey)) { + self.close(); + + evt.preventDefault(); + } else if (key === KEYS.ENTER) { + self.trigger('results:select', {}); + + evt.preventDefault(); + } else if ((key === KEYS.SPACE && evt.ctrlKey)) { + self.trigger('results:toggle', {}); + + evt.preventDefault(); + } else if (key === KEYS.UP) { + self.trigger('results:previous', {}); + + evt.preventDefault(); + } else if (key === KEYS.DOWN) { + self.trigger('results:next', {}); + + evt.preventDefault(); + } + } else { + if (key === KEYS.ENTER || key === KEYS.SPACE || + (key === KEYS.DOWN && evt.altKey)) { + self.open(); + + evt.preventDefault(); + } + } + }); + }; + + Select2.prototype._syncAttributes = function () { + this.options.set('disabled', this.$element.prop('disabled')); + + if (this.options.get('disabled')) { + if (this.isOpen()) { + this.close(); + } + + this.trigger('disable', {}); + } else { + this.trigger('enable', {}); + } + }; + + Select2.prototype._syncSubtree = function (evt, mutations) { + var changed = false; + var self = this; + + // Ignore any mutation events raised for elements that aren't options or + // optgroups. This handles the case when the select element is destroyed + if ( + evt && evt.target && ( + evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP' + ) + ) { + return; + } + + if (!mutations) { + // If mutation events aren't supported, then we can only assume that the + // change affected the selections + changed = true; + } else if (mutations.addedNodes && mutations.addedNodes.length > 0) { + for (var n = 0; n < mutations.addedNodes.length; n++) { + var node = mutations.addedNodes[n]; + + if (node.selected) { + changed = true; + } + } + } else if (mutations.removedNodes && mutations.removedNodes.length > 0) { + changed = true; + } + + // Only re-pull the data if we think there is a change + if (changed) { + this.dataAdapter.current(function (currentData) { + self.trigger('selection:update', { + data: currentData + }); + }); + } + }; + + /** + * Override the trigger method to automatically trigger pre-events when + * there are events that can be prevented. + */ + Select2.prototype.trigger = function (name, args) { + var actualTrigger = Select2.__super__.trigger; + var preTriggerMap = { + 'open': 'opening', + 'close': 'closing', + 'select': 'selecting', + 'unselect': 'unselecting' + }; + + if (args === undefined) { + args = {}; + } + + if (name in preTriggerMap) { + var preTriggerName = preTriggerMap[name]; + var preTriggerArgs = { + prevented: false, + name: name, + args: args + }; + + actualTrigger.call(this, preTriggerName, preTriggerArgs); + + if (preTriggerArgs.prevented) { + args.prevented = true; + + return; + } + } + + actualTrigger.call(this, name, args); + }; + + Select2.prototype.toggleDropdown = function () { + if (this.options.get('disabled')) { + return; + } + + if (this.isOpen()) { + this.close(); + } else { + this.open(); + } + }; + + Select2.prototype.open = function () { + if (this.isOpen()) { + return; + } + + this.trigger('query', {}); + }; + + Select2.prototype.close = function () { + if (!this.isOpen()) { + return; + } + + this.trigger('close', {}); + }; + + Select2.prototype.isOpen = function () { + return this.$container.hasClass('select2-container--open'); + }; + + Select2.prototype.hasFocus = function () { + return this.$container.hasClass('select2-container--focus'); + }; + + Select2.prototype.focus = function (data) { + // No need to re-trigger focus events if we are already focused + if (this.hasFocus()) { + return; + } + + this.$container.addClass('select2-container--focus'); + this.trigger('focus', {}); + }; + + Select2.prototype.enable = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("enable")` method has been deprecated and will' + + ' be removed in later Select2 versions. Use $element.prop("disabled")' + + ' instead.' + ); + } + + if (args == null || args.length === 0) { + args = [true]; + } + + var disabled = !args[0]; + + this.$element.prop('disabled', disabled); + }; + + Select2.prototype.data = function () { + if (this.options.get('debug') && + arguments.length > 0 && window.console && console.warn) { + console.warn( + 'Select2: Data can no longer be set using `select2("data")`. You ' + + 'should consider setting the value instead using `$element.val()`.' + ); + } + + var data = []; + + this.dataAdapter.current(function (currentData) { + data = currentData; + }); + + return data; + }; + + Select2.prototype.val = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("val")` method has been deprecated and will be' + + ' removed in later Select2 versions. Use $element.val() instead.' + ); + } + + if (args == null || args.length === 0) { + return this.$element.val(); + } + + var newVal = args[0]; + + if ($.isArray(newVal)) { + newVal = $.map(newVal, function (obj) { + return obj.toString(); + }); + } + + this.$element.val(newVal).trigger('change'); + }; + + Select2.prototype.destroy = function () { + this.$container.remove(); + + if (this.$element[0].detachEvent) { + this.$element[0].detachEvent('onpropertychange', this._syncA); + } + + if (this._observer != null) { + this._observer.disconnect(); + this._observer = null; + } else if (this.$element[0].removeEventListener) { + this.$element[0] + .removeEventListener('DOMAttrModified', this._syncA, false); + this.$element[0] + .removeEventListener('DOMNodeInserted', this._syncS, false); + this.$element[0] + .removeEventListener('DOMNodeRemoved', this._syncS, false); + } + + this._syncA = null; + this._syncS = null; + + this.$element.off('.select2'); + this.$element.attr('tabindex', this.$element.data('old-tabindex')); + + this.$element.removeClass('select2-hidden-accessible'); + this.$element.attr('aria-hidden', 'false'); + this.$element.removeData('select2'); + + this.dataAdapter.destroy(); + this.selection.destroy(); + this.dropdown.destroy(); + this.results.destroy(); + + this.dataAdapter = null; + this.selection = null; + this.dropdown = null; + this.results = null; + }; + + Select2.prototype.render = function () { + var $container = $( + '' + + '' + + '' + + '' + ); + + $container.attr('dir', this.options.get('dir')); + + this.$container = $container; + + this.$container.addClass('select2-container--' + this.options.get('theme')); + + $container.data('element', this.$element); + + return $container; + }; + + return Select2; +}); + +S2.define('select2/compat/utils',[ + 'jquery' +], function ($) { + function syncCssClasses ($dest, $src, adapter) { + var classes, replacements = [], adapted; + + classes = $.trim($dest.attr('class')); + + if (classes) { + classes = '' + classes; // for IE which returns object + + $(classes.split(/\s+/)).each(function () { + // Save all Select2 classes + if (this.indexOf('select2-') === 0) { + replacements.push(this); + } + }); + } + + classes = $.trim($src.attr('class')); + + if (classes) { + classes = '' + classes; // for IE which returns object + + $(classes.split(/\s+/)).each(function () { + // Only adapt non-Select2 classes + if (this.indexOf('select2-') !== 0) { + adapted = adapter(this); + + if (adapted != null) { + replacements.push(adapted); + } + } + }); + } + + $dest.attr('class', replacements.join(' ')); + } + + return { + syncCssClasses: syncCssClasses + }; +}); + +S2.define('select2/compat/containerCss',[ + 'jquery', + './utils' +], function ($, CompatUtils) { + // No-op CSS adapter that discards all classes by default + function _containerAdapter (clazz) { + return null; + } + + function ContainerCSS () { } + + ContainerCSS.prototype.render = function (decorated) { + var $container = decorated.call(this); + + var containerCssClass = this.options.get('containerCssClass') || ''; + + if ($.isFunction(containerCssClass)) { + containerCssClass = containerCssClass(this.$element); + } + + var containerCssAdapter = this.options.get('adaptContainerCssClass'); + containerCssAdapter = containerCssAdapter || _containerAdapter; + + if (containerCssClass.indexOf(':all:') !== -1) { + containerCssClass = containerCssClass.replace(':all:', ''); + + var _cssAdapter = containerCssAdapter; + + containerCssAdapter = function (clazz) { + var adapted = _cssAdapter(clazz); + + if (adapted != null) { + // Append the old one along with the adapted one + return adapted + ' ' + clazz; + } + + return clazz; + }; + } + + var containerCss = this.options.get('containerCss') || {}; + + if ($.isFunction(containerCss)) { + containerCss = containerCss(this.$element); + } + + CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter); + + $container.css(containerCss); + $container.addClass(containerCssClass); + + return $container; + }; + + return ContainerCSS; +}); + +S2.define('select2/compat/dropdownCss',[ + 'jquery', + './utils' +], function ($, CompatUtils) { + // No-op CSS adapter that discards all classes by default + function _dropdownAdapter (clazz) { + return null; + } + + function DropdownCSS () { } + + DropdownCSS.prototype.render = function (decorated) { + var $dropdown = decorated.call(this); + + var dropdownCssClass = this.options.get('dropdownCssClass') || ''; + + if ($.isFunction(dropdownCssClass)) { + dropdownCssClass = dropdownCssClass(this.$element); + } + + var dropdownCssAdapter = this.options.get('adaptDropdownCssClass'); + dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter; + + if (dropdownCssClass.indexOf(':all:') !== -1) { + dropdownCssClass = dropdownCssClass.replace(':all:', ''); + + var _cssAdapter = dropdownCssAdapter; + + dropdownCssAdapter = function (clazz) { + var adapted = _cssAdapter(clazz); + + if (adapted != null) { + // Append the old one along with the adapted one + return adapted + ' ' + clazz; + } + + return clazz; + }; + } + + var dropdownCss = this.options.get('dropdownCss') || {}; + + if ($.isFunction(dropdownCss)) { + dropdownCss = dropdownCss(this.$element); + } + + CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter); + + $dropdown.css(dropdownCss); + $dropdown.addClass(dropdownCssClass); + + return $dropdown; + }; + + return DropdownCSS; +}); + +S2.define('select2/compat/initSelection',[ + 'jquery' +], function ($) { + function InitSelection (decorated, $element, options) { + if (options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `initSelection` option has been deprecated in favor' + + ' of a custom data adapter that overrides the `current` method. ' + + 'This method is now called multiple times instead of a single ' + + 'time when the instance is initialized. Support will be removed ' + + 'for the `initSelection` option in future versions of Select2' + ); + } + + this.initSelection = options.get('initSelection'); + this._isInitialized = false; + + decorated.call(this, $element, options); + } + + InitSelection.prototype.current = function (decorated, callback) { + var self = this; + + if (this._isInitialized) { + decorated.call(this, callback); + + return; + } + + this.initSelection.call(null, this.$element, function (data) { + self._isInitialized = true; + + if (!$.isArray(data)) { + data = [data]; + } + + callback(data); + }); + }; + + return InitSelection; +}); + +S2.define('select2/compat/inputData',[ + 'jquery' +], function ($) { + function InputData (decorated, $element, options) { + this._currentData = []; + this._valueSeparator = options.get('valueSeparator') || ','; + + if ($element.prop('type') === 'hidden') { + if (options.get('debug') && console && console.warn) { + console.warn( + 'Select2: Using a hidden input with Select2 is no longer ' + + 'supported and may stop working in the future. It is recommended ' + + 'to use a `');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return this._transferTabIndex(),d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.trigger("focus")}),b.on("close",function(){e.$search.val(""),e.$search.removeAttr("aria-activedescendant"),e.$search.trigger("focus")}),b.on("enable",function(){e.$search.prop("disabled",!1),e._transferTabIndex()}),b.on("disable",function(){e.$search.prop("disabled",!0)}),b.on("focus",function(a){e.$search.trigger("focus")}),b.on("results:focus",function(a){e.$search.attr("aria-activedescendant",a.id)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e._handleBlur(a)}),this.$selection.on("keydown",".select2-search--inline",function(a){a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented();var b=a.which;if(b===c.BACKSPACE&&""===e.$search.val()){var d=e.$searchContainer.prev(".select2-selection__choice");if(d.length>0){var f=d.data("data");e.searchRemoveChoice(f),a.preventDefault()}}});var f=document.documentMode,g=f&&11>=f;this.$selection.on("input.searchcheck",".select2-search--inline",function(a){return g?void e.$selection.off("input.search input.searchcheck"):void e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(a){if(g&&"input"===a.type)return void e.$selection.off("input.search input.searchcheck");var b=a.which;b!=c.SHIFT&&b!=c.CTRL&&b!=c.ALT&&b!=c.TAB&&e.handleSearch(a)})},d.prototype._transferTabIndex=function(a){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){var c=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch(),c&&this.$search.focus()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.$search.val(b.text),this.handleSearch()},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{var b=this.$search.val().length+1;a=.75*b+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){var a={"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ω":"ω","ς":"σ"};return a}),b.define("select2/data/base",["../utils"],function(a){function b(a,c){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(a){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(a,b){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(a,b){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),d+=null!=c.id?"-"+c.id.toString():"-"+a.generateChars(4)},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change"); +if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){d.status&&"0"===d.status||e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&null!=a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.call(this,c,d),a.isArray(e))for(var h=0;h0&&b.term.length>this.maximumInputLength?void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;return d.maximumSelectionLength>0&&f>=d.maximumSelectionLength?void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}}):void a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.bind=function(){},c.prototype.position=function(a,b){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a,b){function c(){}return c.prototype.render=function(b){var c=b.call(this),d=a('');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},c.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(b){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("focus",function(){c.isOpen()&&e.$search.focus()}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){var b=e.showSearch(a);b?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},c.prototype.handleSearch=function(a){if(!this._keyUpPrevented){var b=this.$search.val();this.trigger("query",{term:b})}this._keyUpPrevented=!1},c.prototype.showSearch=function(a,b){return!0},c}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){var c=e.$results.offset().top+e.$results.outerHeight(!1),d=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1);c+50>=d&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('
      • '),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(b,c,d){this.$dropdownParent=d.get("dropdownParent")||a(document.body),b.call(this,c,d)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.destroy=function(a){a.call(this),this.$dropdownContainer.remove()},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a(""),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(a){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c,d){var e=this,f="scroll.select2."+d.id,g="resize.select2."+d.id,h="orientationchange.select2."+d.id,i=this.$container.parents().filter(b.hasScroll);i.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),i.on(f,function(b){var c=a(this).data("select2-scroll-position");a(this).scrollTop(c.y)}),a(window).on(f+" "+g+" "+h,function(a){e._positionDropdown(),e._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c,d){var e="scroll.select2."+d.id,f="resize.select2."+d.id,g="orientationchange.select2."+d.id,h=this.$container.parents().filter(b.hasScroll);h.off(e),a(window).off(e+" "+f+" "+g)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=this.$container.offset();f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.topf.bottom+h.height,l={left:f.left,top:g.bottom},m=this.$dropdownParent;"static"===m.css("position")&&(m=m.offsetParent());var n=m.offset();l.top-=n.top,l.left-=n.left,c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-n.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.position="relative",a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(a){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),(null!=l.tokenSeparators||null!=l.tokenizer)&&(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.multiple?l.selectionAdapter=e:l.selectionAdapter=d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){var h=e.children[g],i=c(d,h);null==i&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var j=b(e.text).toUpperCase(),k=b(d.term).toUpperCase();return j.indexOf(k)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)};var E=new D;return E}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(a.prop("dir")?this.options.dir=a.prop("dir"):a.closest("[dir]").prop("dir")?this.options.dir=a.closest("[dir]").prop("dir"):this.options.dir="ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b=b.replace(/(:|\.|\[|\]|,)/g,""),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return 0>=e?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;i>h;h+=1){var j=g[h].replace(/\s/g,""),k=j.match(c);if(null!==k&&k.length>=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this.$element.on("focus.select2",function(a){b.trigger("focus",a)}),this._syncA=c.bind(this._syncAttributes,this),this._syncS=c.bind(this._syncSubtree,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._syncA);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._syncA),a.each(c,b._syncS)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})):this.$element[0].addEventListener&&(this.$element[0].addEventListener("DOMAttrModified",b._syncA,!1),this.$element[0].addEventListener("DOMNodeInserted",b._syncS,!1),this.$element[0].addEventListener("DOMNodeRemoved",b._syncS,!1))},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle","focus"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("focus",function(a){b.focus(a)}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open",{}),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ESC||c===d.TAB||c===d.UP&&b.altKey?(a.close(),b.preventDefault()):c===d.ENTER?(a.trigger("results:select",{}),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle",{}),b.preventDefault()):c===d.UP?(a.trigger("results:previous",{}),b.preventDefault()):c===d.DOWN&&(a.trigger("results:next",{}),b.preventDefault()):(c===d.ENTER||c===d.SPACE||c===d.DOWN&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},e.prototype._syncSubtree=function(a,b){var c=!1,d=this;if(!a||!a.target||"OPTION"===a.target.nodeName||"OPTGROUP"===a.target.nodeName){if(b)if(b.addedNodes&&b.addedNodes.length>0)for(var e=0;e0&&(c=!0);else c=!0;c&&this.dataAdapter.current(function(a){d.trigger("selection:update",{data:a})})}},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(void 0===b&&(b={}),a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||this.trigger("query",{})},e.prototype.close=function(){this.isOpen()&&this.trigger("close",{})},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")},e.prototype.focus=function(a){this.hasFocus()||(this.$container.addClass("select2-container--focus"),this.trigger("focus",{}))},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),(null==a||0===a.length)&&(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._syncA),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&(this.$element[0].removeEventListener("DOMAttrModified",this._syncA,!1),this.$element[0].removeEventListener("DOMNodeInserted",this._syncS,!1),this.$element[0].removeEventListener("DOMNodeRemoved",this._syncS,!1)),this._syncA=null,this._syncS=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null; +},e.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("select2/compat/utils",["jquery"],function(a){function b(b,c,d){var e,f,g=[];e=a.trim(b.attr("class")),e&&(e=""+e,a(e.split(/\s+/)).each(function(){0===this.indexOf("select2-")&&g.push(this)})),e=a.trim(c.attr("class")),e&&(e=""+e,a(e.split(/\s+/)).each(function(){0!==this.indexOf("select2-")&&(f=d(this),null!=f&&g.push(f))})),b.attr("class",g.join(" "))}return{syncCssClasses:b}}),b.define("select2/compat/containerCss",["jquery","./utils"],function(a,b){function c(a){return null}function d(){}return d.prototype.render=function(d){var e=d.call(this),f=this.options.get("containerCssClass")||"";a.isFunction(f)&&(f=f(this.$element));var g=this.options.get("adaptContainerCssClass");if(g=g||c,-1!==f.indexOf(":all:")){f=f.replace(":all:","");var h=g;g=function(a){var b=h(a);return null!=b?b+" "+a:a}}var i=this.options.get("containerCss")||{};return a.isFunction(i)&&(i=i(this.$element)),b.syncCssClasses(e,this.$element,g),e.css(i),e.addClass(f),e},d}),b.define("select2/compat/dropdownCss",["jquery","./utils"],function(a,b){function c(a){return null}function d(){}return d.prototype.render=function(d){var e=d.call(this),f=this.options.get("dropdownCssClass")||"";a.isFunction(f)&&(f=f(this.$element));var g=this.options.get("adaptDropdownCssClass");if(g=g||c,-1!==f.indexOf(":all:")){f=f.replace(":all:","");var h=g;g=function(a){var b=h(a);return null!=b?b+" "+a:a}}var i=this.options.get("dropdownCss")||{};return a.isFunction(i)&&(i=i(this.$element)),b.syncCssClasses(e,this.$element,g),e.css(i),e.addClass(f),e},d}),b.define("select2/compat/initSelection",["jquery"],function(a){function b(a,b,c){c.get("debug")&&window.console&&console.warn&&console.warn("Select2: The `initSelection` option has been deprecated in favor of a custom data adapter that overrides the `current` method. This method is now called multiple times instead of a single time when the instance is initialized. Support will be removed for the `initSelection` option in future versions of Select2"),this.initSelection=c.get("initSelection"),this._isInitialized=!1,a.call(this,b,c)}return b.prototype.current=function(b,c){var d=this;return this._isInitialized?void b.call(this,c):void this.initSelection.call(null,this.$element,function(b){d._isInitialized=!0,a.isArray(b)||(b=[b]),c(b)})},b}),b.define("select2/compat/inputData",["jquery"],function(a){function b(a,b,c){this._currentData=[],this._valueSeparator=c.get("valueSeparator")||",","hidden"===b.prop("type")&&c.get("debug")&&console&&console.warn&&console.warn("Select2: Using a hidden input with Select2 is no longer supported and may stop working in the future. It is recommended to use a `' + + '' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + var $rendered = decorated.call(this); + + this._transferTabIndex(); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('open', function () { + self.$search.trigger('focus'); + }); + + container.on('close', function () { + self.$search.val(''); + self.$search.removeAttr('aria-activedescendant'); + self.$search.trigger('focus'); + }); + + container.on('enable', function () { + self.$search.prop('disabled', false); + + self._transferTabIndex(); + }); + + container.on('disable', function () { + self.$search.prop('disabled', true); + }); + + container.on('focus', function (evt) { + self.$search.trigger('focus'); + }); + + container.on('results:focus', function (params) { + self.$search.attr('aria-activedescendant', params.id); + }); + + this.$selection.on('focusin', '.select2-search--inline', function (evt) { + self.trigger('focus', evt); + }); + + this.$selection.on('focusout', '.select2-search--inline', function (evt) { + self._handleBlur(evt); + }); + + this.$selection.on('keydown', '.select2-search--inline', function (evt) { + evt.stopPropagation(); + + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + + var key = evt.which; + + if (key === KEYS.BACKSPACE && self.$search.val() === '') { + var $previousChoice = self.$searchContainer + .prev('.select2-selection__choice'); + + if ($previousChoice.length > 0) { + var item = $previousChoice.data('data'); + + self.searchRemoveChoice(item); + + evt.preventDefault(); + } + } + }); + + // Try to detect the IE version should the `documentMode` property that + // is stored on the document. This is only implemented in IE and is + // slightly cleaner than doing a user agent check. + // This property is not available in Edge, but Edge also doesn't have + // this bug. + var msie = document.documentMode; + var disableInputEvents = msie && msie <= 11; + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$selection.on( + 'input.searchcheck', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents) { + self.$selection.off('input.search input.searchcheck'); + return; + } + + // Unbind the duplicated `keyup` event + self.$selection.off('keyup.search'); + } + ); + + this.$selection.on( + 'keyup.search input.search', + '.select2-search--inline', + function (evt) { + // IE will trigger the `input` event when a placeholder is used on a + // search box. To get around this issue, we are forced to ignore all + // `input` events in IE and keep using `keyup`. + if (disableInputEvents && evt.type === 'input') { + self.$selection.off('input.search input.searchcheck'); + return; + } + + var key = evt.which; + + // We can freely ignore events from modifier keys + if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { + return; + } + + // Tabbing will be handled during the `keydown` phase + if (key == KEYS.TAB) { + return; + } + + self.handleSearch(evt); + } + ); + }; + + /** + * This method will transfer the tabindex attribute from the rendered + * selection to the search box. This allows for the search box to be used as + * the primary focus instead of the selection container. + * + * @private + */ + Search.prototype._transferTabIndex = function (decorated) { + this.$search.attr('tabindex', this.$selection.attr('tabindex')); + this.$selection.attr('tabindex', '-1'); + }; + + Search.prototype.createPlaceholder = function (decorated, placeholder) { + this.$search.attr('placeholder', placeholder.text); + }; + + Search.prototype.update = function (decorated, data) { + var searchHadFocus = this.$search[0] == document.activeElement; + + this.$search.attr('placeholder', ''); + + decorated.call(this, data); + + this.$selection.find('.select2-selection__rendered') + .append(this.$searchContainer); + + this.resizeSearch(); + if (searchHadFocus) { + this.$search.focus(); + } + }; + + Search.prototype.handleSearch = function () { + this.resizeSearch(); + + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.searchRemoveChoice = function (decorated, item) { + this.trigger('unselect', { + data: item + }); + + this.$search.val(item.text); + this.handleSearch(); + }; + + Search.prototype.resizeSearch = function () { + this.$search.css('width', '25px'); + + var width = ''; + + if (this.$search.attr('placeholder') !== '') { + width = this.$selection.find('.select2-selection__rendered').innerWidth(); + } else { + var minimumWidth = this.$search.val().length + 1; + + width = (minimumWidth * 0.75) + 'em'; + } + + this.$search.css('width', width); + }; + + return Search; +}); + +S2.define('select2/selection/eventRelay',[ + 'jquery' +], function ($) { + function EventRelay () { } + + EventRelay.prototype.bind = function (decorated, container, $container) { + var self = this; + var relayEvents = [ + 'open', 'opening', + 'close', 'closing', + 'select', 'selecting', + 'unselect', 'unselecting' + ]; + + var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting']; + + decorated.call(this, container, $container); + + container.on('*', function (name, params) { + // Ignore events that should not be relayed + if ($.inArray(name, relayEvents) === -1) { + return; + } + + // The parameters should always be an object + params = params || {}; + + // Generate the jQuery event for the Select2 event + var evt = $.Event('select2:' + name, { + params: params + }); + + self.$element.trigger(evt); + + // Only handle preventable events if it was one + if ($.inArray(name, preventableEvents) === -1) { + return; + } + + params.prevented = evt.isDefaultPrevented(); + }); + }; + + return EventRelay; +}); + +S2.define('select2/translation',[ + 'jquery', + 'require' +], function ($, require) { + function Translation (dict) { + this.dict = dict || {}; + } + + Translation.prototype.all = function () { + return this.dict; + }; + + Translation.prototype.get = function (key) { + return this.dict[key]; + }; + + Translation.prototype.extend = function (translation) { + this.dict = $.extend({}, translation.all(), this.dict); + }; + + // Static functions + + Translation._cache = {}; + + Translation.loadPath = function (path) { + if (!(path in Translation._cache)) { + var translations = require(path); + + Translation._cache[path] = translations; + } + + return new Translation(Translation._cache[path]); + }; + + return Translation; +}); + +S2.define('select2/diacritics',[ + +], function () { + var diacritics = { + '\u24B6': 'A', + '\uFF21': 'A', + '\u00C0': 'A', + '\u00C1': 'A', + '\u00C2': 'A', + '\u1EA6': 'A', + '\u1EA4': 'A', + '\u1EAA': 'A', + '\u1EA8': 'A', + '\u00C3': 'A', + '\u0100': 'A', + '\u0102': 'A', + '\u1EB0': 'A', + '\u1EAE': 'A', + '\u1EB4': 'A', + '\u1EB2': 'A', + '\u0226': 'A', + '\u01E0': 'A', + '\u00C4': 'A', + '\u01DE': 'A', + '\u1EA2': 'A', + '\u00C5': 'A', + '\u01FA': 'A', + '\u01CD': 'A', + '\u0200': 'A', + '\u0202': 'A', + '\u1EA0': 'A', + '\u1EAC': 'A', + '\u1EB6': 'A', + '\u1E00': 'A', + '\u0104': 'A', + '\u023A': 'A', + '\u2C6F': 'A', + '\uA732': 'AA', + '\u00C6': 'AE', + '\u01FC': 'AE', + '\u01E2': 'AE', + '\uA734': 'AO', + '\uA736': 'AU', + '\uA738': 'AV', + '\uA73A': 'AV', + '\uA73C': 'AY', + '\u24B7': 'B', + '\uFF22': 'B', + '\u1E02': 'B', + '\u1E04': 'B', + '\u1E06': 'B', + '\u0243': 'B', + '\u0182': 'B', + '\u0181': 'B', + '\u24B8': 'C', + '\uFF23': 'C', + '\u0106': 'C', + '\u0108': 'C', + '\u010A': 'C', + '\u010C': 'C', + '\u00C7': 'C', + '\u1E08': 'C', + '\u0187': 'C', + '\u023B': 'C', + '\uA73E': 'C', + '\u24B9': 'D', + '\uFF24': 'D', + '\u1E0A': 'D', + '\u010E': 'D', + '\u1E0C': 'D', + '\u1E10': 'D', + '\u1E12': 'D', + '\u1E0E': 'D', + '\u0110': 'D', + '\u018B': 'D', + '\u018A': 'D', + '\u0189': 'D', + '\uA779': 'D', + '\u01F1': 'DZ', + '\u01C4': 'DZ', + '\u01F2': 'Dz', + '\u01C5': 'Dz', + '\u24BA': 'E', + '\uFF25': 'E', + '\u00C8': 'E', + '\u00C9': 'E', + '\u00CA': 'E', + '\u1EC0': 'E', + '\u1EBE': 'E', + '\u1EC4': 'E', + '\u1EC2': 'E', + '\u1EBC': 'E', + '\u0112': 'E', + '\u1E14': 'E', + '\u1E16': 'E', + '\u0114': 'E', + '\u0116': 'E', + '\u00CB': 'E', + '\u1EBA': 'E', + '\u011A': 'E', + '\u0204': 'E', + '\u0206': 'E', + '\u1EB8': 'E', + '\u1EC6': 'E', + '\u0228': 'E', + '\u1E1C': 'E', + '\u0118': 'E', + '\u1E18': 'E', + '\u1E1A': 'E', + '\u0190': 'E', + '\u018E': 'E', + '\u24BB': 'F', + '\uFF26': 'F', + '\u1E1E': 'F', + '\u0191': 'F', + '\uA77B': 'F', + '\u24BC': 'G', + '\uFF27': 'G', + '\u01F4': 'G', + '\u011C': 'G', + '\u1E20': 'G', + '\u011E': 'G', + '\u0120': 'G', + '\u01E6': 'G', + '\u0122': 'G', + '\u01E4': 'G', + '\u0193': 'G', + '\uA7A0': 'G', + '\uA77D': 'G', + '\uA77E': 'G', + '\u24BD': 'H', + '\uFF28': 'H', + '\u0124': 'H', + '\u1E22': 'H', + '\u1E26': 'H', + '\u021E': 'H', + '\u1E24': 'H', + '\u1E28': 'H', + '\u1E2A': 'H', + '\u0126': 'H', + '\u2C67': 'H', + '\u2C75': 'H', + '\uA78D': 'H', + '\u24BE': 'I', + '\uFF29': 'I', + '\u00CC': 'I', + '\u00CD': 'I', + '\u00CE': 'I', + '\u0128': 'I', + '\u012A': 'I', + '\u012C': 'I', + '\u0130': 'I', + '\u00CF': 'I', + '\u1E2E': 'I', + '\u1EC8': 'I', + '\u01CF': 'I', + '\u0208': 'I', + '\u020A': 'I', + '\u1ECA': 'I', + '\u012E': 'I', + '\u1E2C': 'I', + '\u0197': 'I', + '\u24BF': 'J', + '\uFF2A': 'J', + '\u0134': 'J', + '\u0248': 'J', + '\u24C0': 'K', + '\uFF2B': 'K', + '\u1E30': 'K', + '\u01E8': 'K', + '\u1E32': 'K', + '\u0136': 'K', + '\u1E34': 'K', + '\u0198': 'K', + '\u2C69': 'K', + '\uA740': 'K', + '\uA742': 'K', + '\uA744': 'K', + '\uA7A2': 'K', + '\u24C1': 'L', + '\uFF2C': 'L', + '\u013F': 'L', + '\u0139': 'L', + '\u013D': 'L', + '\u1E36': 'L', + '\u1E38': 'L', + '\u013B': 'L', + '\u1E3C': 'L', + '\u1E3A': 'L', + '\u0141': 'L', + '\u023D': 'L', + '\u2C62': 'L', + '\u2C60': 'L', + '\uA748': 'L', + '\uA746': 'L', + '\uA780': 'L', + '\u01C7': 'LJ', + '\u01C8': 'Lj', + '\u24C2': 'M', + '\uFF2D': 'M', + '\u1E3E': 'M', + '\u1E40': 'M', + '\u1E42': 'M', + '\u2C6E': 'M', + '\u019C': 'M', + '\u24C3': 'N', + '\uFF2E': 'N', + '\u01F8': 'N', + '\u0143': 'N', + '\u00D1': 'N', + '\u1E44': 'N', + '\u0147': 'N', + '\u1E46': 'N', + '\u0145': 'N', + '\u1E4A': 'N', + '\u1E48': 'N', + '\u0220': 'N', + '\u019D': 'N', + '\uA790': 'N', + '\uA7A4': 'N', + '\u01CA': 'NJ', + '\u01CB': 'Nj', + '\u24C4': 'O', + '\uFF2F': 'O', + '\u00D2': 'O', + '\u00D3': 'O', + '\u00D4': 'O', + '\u1ED2': 'O', + '\u1ED0': 'O', + '\u1ED6': 'O', + '\u1ED4': 'O', + '\u00D5': 'O', + '\u1E4C': 'O', + '\u022C': 'O', + '\u1E4E': 'O', + '\u014C': 'O', + '\u1E50': 'O', + '\u1E52': 'O', + '\u014E': 'O', + '\u022E': 'O', + '\u0230': 'O', + '\u00D6': 'O', + '\u022A': 'O', + '\u1ECE': 'O', + '\u0150': 'O', + '\u01D1': 'O', + '\u020C': 'O', + '\u020E': 'O', + '\u01A0': 'O', + '\u1EDC': 'O', + '\u1EDA': 'O', + '\u1EE0': 'O', + '\u1EDE': 'O', + '\u1EE2': 'O', + '\u1ECC': 'O', + '\u1ED8': 'O', + '\u01EA': 'O', + '\u01EC': 'O', + '\u00D8': 'O', + '\u01FE': 'O', + '\u0186': 'O', + '\u019F': 'O', + '\uA74A': 'O', + '\uA74C': 'O', + '\u01A2': 'OI', + '\uA74E': 'OO', + '\u0222': 'OU', + '\u24C5': 'P', + '\uFF30': 'P', + '\u1E54': 'P', + '\u1E56': 'P', + '\u01A4': 'P', + '\u2C63': 'P', + '\uA750': 'P', + '\uA752': 'P', + '\uA754': 'P', + '\u24C6': 'Q', + '\uFF31': 'Q', + '\uA756': 'Q', + '\uA758': 'Q', + '\u024A': 'Q', + '\u24C7': 'R', + '\uFF32': 'R', + '\u0154': 'R', + '\u1E58': 'R', + '\u0158': 'R', + '\u0210': 'R', + '\u0212': 'R', + '\u1E5A': 'R', + '\u1E5C': 'R', + '\u0156': 'R', + '\u1E5E': 'R', + '\u024C': 'R', + '\u2C64': 'R', + '\uA75A': 'R', + '\uA7A6': 'R', + '\uA782': 'R', + '\u24C8': 'S', + '\uFF33': 'S', + '\u1E9E': 'S', + '\u015A': 'S', + '\u1E64': 'S', + '\u015C': 'S', + '\u1E60': 'S', + '\u0160': 'S', + '\u1E66': 'S', + '\u1E62': 'S', + '\u1E68': 'S', + '\u0218': 'S', + '\u015E': 'S', + '\u2C7E': 'S', + '\uA7A8': 'S', + '\uA784': 'S', + '\u24C9': 'T', + '\uFF34': 'T', + '\u1E6A': 'T', + '\u0164': 'T', + '\u1E6C': 'T', + '\u021A': 'T', + '\u0162': 'T', + '\u1E70': 'T', + '\u1E6E': 'T', + '\u0166': 'T', + '\u01AC': 'T', + '\u01AE': 'T', + '\u023E': 'T', + '\uA786': 'T', + '\uA728': 'TZ', + '\u24CA': 'U', + '\uFF35': 'U', + '\u00D9': 'U', + '\u00DA': 'U', + '\u00DB': 'U', + '\u0168': 'U', + '\u1E78': 'U', + '\u016A': 'U', + '\u1E7A': 'U', + '\u016C': 'U', + '\u00DC': 'U', + '\u01DB': 'U', + '\u01D7': 'U', + '\u01D5': 'U', + '\u01D9': 'U', + '\u1EE6': 'U', + '\u016E': 'U', + '\u0170': 'U', + '\u01D3': 'U', + '\u0214': 'U', + '\u0216': 'U', + '\u01AF': 'U', + '\u1EEA': 'U', + '\u1EE8': 'U', + '\u1EEE': 'U', + '\u1EEC': 'U', + '\u1EF0': 'U', + '\u1EE4': 'U', + '\u1E72': 'U', + '\u0172': 'U', + '\u1E76': 'U', + '\u1E74': 'U', + '\u0244': 'U', + '\u24CB': 'V', + '\uFF36': 'V', + '\u1E7C': 'V', + '\u1E7E': 'V', + '\u01B2': 'V', + '\uA75E': 'V', + '\u0245': 'V', + '\uA760': 'VY', + '\u24CC': 'W', + '\uFF37': 'W', + '\u1E80': 'W', + '\u1E82': 'W', + '\u0174': 'W', + '\u1E86': 'W', + '\u1E84': 'W', + '\u1E88': 'W', + '\u2C72': 'W', + '\u24CD': 'X', + '\uFF38': 'X', + '\u1E8A': 'X', + '\u1E8C': 'X', + '\u24CE': 'Y', + '\uFF39': 'Y', + '\u1EF2': 'Y', + '\u00DD': 'Y', + '\u0176': 'Y', + '\u1EF8': 'Y', + '\u0232': 'Y', + '\u1E8E': 'Y', + '\u0178': 'Y', + '\u1EF6': 'Y', + '\u1EF4': 'Y', + '\u01B3': 'Y', + '\u024E': 'Y', + '\u1EFE': 'Y', + '\u24CF': 'Z', + '\uFF3A': 'Z', + '\u0179': 'Z', + '\u1E90': 'Z', + '\u017B': 'Z', + '\u017D': 'Z', + '\u1E92': 'Z', + '\u1E94': 'Z', + '\u01B5': 'Z', + '\u0224': 'Z', + '\u2C7F': 'Z', + '\u2C6B': 'Z', + '\uA762': 'Z', + '\u24D0': 'a', + '\uFF41': 'a', + '\u1E9A': 'a', + '\u00E0': 'a', + '\u00E1': 'a', + '\u00E2': 'a', + '\u1EA7': 'a', + '\u1EA5': 'a', + '\u1EAB': 'a', + '\u1EA9': 'a', + '\u00E3': 'a', + '\u0101': 'a', + '\u0103': 'a', + '\u1EB1': 'a', + '\u1EAF': 'a', + '\u1EB5': 'a', + '\u1EB3': 'a', + '\u0227': 'a', + '\u01E1': 'a', + '\u00E4': 'a', + '\u01DF': 'a', + '\u1EA3': 'a', + '\u00E5': 'a', + '\u01FB': 'a', + '\u01CE': 'a', + '\u0201': 'a', + '\u0203': 'a', + '\u1EA1': 'a', + '\u1EAD': 'a', + '\u1EB7': 'a', + '\u1E01': 'a', + '\u0105': 'a', + '\u2C65': 'a', + '\u0250': 'a', + '\uA733': 'aa', + '\u00E6': 'ae', + '\u01FD': 'ae', + '\u01E3': 'ae', + '\uA735': 'ao', + '\uA737': 'au', + '\uA739': 'av', + '\uA73B': 'av', + '\uA73D': 'ay', + '\u24D1': 'b', + '\uFF42': 'b', + '\u1E03': 'b', + '\u1E05': 'b', + '\u1E07': 'b', + '\u0180': 'b', + '\u0183': 'b', + '\u0253': 'b', + '\u24D2': 'c', + '\uFF43': 'c', + '\u0107': 'c', + '\u0109': 'c', + '\u010B': 'c', + '\u010D': 'c', + '\u00E7': 'c', + '\u1E09': 'c', + '\u0188': 'c', + '\u023C': 'c', + '\uA73F': 'c', + '\u2184': 'c', + '\u24D3': 'd', + '\uFF44': 'd', + '\u1E0B': 'd', + '\u010F': 'd', + '\u1E0D': 'd', + '\u1E11': 'd', + '\u1E13': 'd', + '\u1E0F': 'd', + '\u0111': 'd', + '\u018C': 'd', + '\u0256': 'd', + '\u0257': 'd', + '\uA77A': 'd', + '\u01F3': 'dz', + '\u01C6': 'dz', + '\u24D4': 'e', + '\uFF45': 'e', + '\u00E8': 'e', + '\u00E9': 'e', + '\u00EA': 'e', + '\u1EC1': 'e', + '\u1EBF': 'e', + '\u1EC5': 'e', + '\u1EC3': 'e', + '\u1EBD': 'e', + '\u0113': 'e', + '\u1E15': 'e', + '\u1E17': 'e', + '\u0115': 'e', + '\u0117': 'e', + '\u00EB': 'e', + '\u1EBB': 'e', + '\u011B': 'e', + '\u0205': 'e', + '\u0207': 'e', + '\u1EB9': 'e', + '\u1EC7': 'e', + '\u0229': 'e', + '\u1E1D': 'e', + '\u0119': 'e', + '\u1E19': 'e', + '\u1E1B': 'e', + '\u0247': 'e', + '\u025B': 'e', + '\u01DD': 'e', + '\u24D5': 'f', + '\uFF46': 'f', + '\u1E1F': 'f', + '\u0192': 'f', + '\uA77C': 'f', + '\u24D6': 'g', + '\uFF47': 'g', + '\u01F5': 'g', + '\u011D': 'g', + '\u1E21': 'g', + '\u011F': 'g', + '\u0121': 'g', + '\u01E7': 'g', + '\u0123': 'g', + '\u01E5': 'g', + '\u0260': 'g', + '\uA7A1': 'g', + '\u1D79': 'g', + '\uA77F': 'g', + '\u24D7': 'h', + '\uFF48': 'h', + '\u0125': 'h', + '\u1E23': 'h', + '\u1E27': 'h', + '\u021F': 'h', + '\u1E25': 'h', + '\u1E29': 'h', + '\u1E2B': 'h', + '\u1E96': 'h', + '\u0127': 'h', + '\u2C68': 'h', + '\u2C76': 'h', + '\u0265': 'h', + '\u0195': 'hv', + '\u24D8': 'i', + '\uFF49': 'i', + '\u00EC': 'i', + '\u00ED': 'i', + '\u00EE': 'i', + '\u0129': 'i', + '\u012B': 'i', + '\u012D': 'i', + '\u00EF': 'i', + '\u1E2F': 'i', + '\u1EC9': 'i', + '\u01D0': 'i', + '\u0209': 'i', + '\u020B': 'i', + '\u1ECB': 'i', + '\u012F': 'i', + '\u1E2D': 'i', + '\u0268': 'i', + '\u0131': 'i', + '\u24D9': 'j', + '\uFF4A': 'j', + '\u0135': 'j', + '\u01F0': 'j', + '\u0249': 'j', + '\u24DA': 'k', + '\uFF4B': 'k', + '\u1E31': 'k', + '\u01E9': 'k', + '\u1E33': 'k', + '\u0137': 'k', + '\u1E35': 'k', + '\u0199': 'k', + '\u2C6A': 'k', + '\uA741': 'k', + '\uA743': 'k', + '\uA745': 'k', + '\uA7A3': 'k', + '\u24DB': 'l', + '\uFF4C': 'l', + '\u0140': 'l', + '\u013A': 'l', + '\u013E': 'l', + '\u1E37': 'l', + '\u1E39': 'l', + '\u013C': 'l', + '\u1E3D': 'l', + '\u1E3B': 'l', + '\u017F': 'l', + '\u0142': 'l', + '\u019A': 'l', + '\u026B': 'l', + '\u2C61': 'l', + '\uA749': 'l', + '\uA781': 'l', + '\uA747': 'l', + '\u01C9': 'lj', + '\u24DC': 'm', + '\uFF4D': 'm', + '\u1E3F': 'm', + '\u1E41': 'm', + '\u1E43': 'm', + '\u0271': 'm', + '\u026F': 'm', + '\u24DD': 'n', + '\uFF4E': 'n', + '\u01F9': 'n', + '\u0144': 'n', + '\u00F1': 'n', + '\u1E45': 'n', + '\u0148': 'n', + '\u1E47': 'n', + '\u0146': 'n', + '\u1E4B': 'n', + '\u1E49': 'n', + '\u019E': 'n', + '\u0272': 'n', + '\u0149': 'n', + '\uA791': 'n', + '\uA7A5': 'n', + '\u01CC': 'nj', + '\u24DE': 'o', + '\uFF4F': 'o', + '\u00F2': 'o', + '\u00F3': 'o', + '\u00F4': 'o', + '\u1ED3': 'o', + '\u1ED1': 'o', + '\u1ED7': 'o', + '\u1ED5': 'o', + '\u00F5': 'o', + '\u1E4D': 'o', + '\u022D': 'o', + '\u1E4F': 'o', + '\u014D': 'o', + '\u1E51': 'o', + '\u1E53': 'o', + '\u014F': 'o', + '\u022F': 'o', + '\u0231': 'o', + '\u00F6': 'o', + '\u022B': 'o', + '\u1ECF': 'o', + '\u0151': 'o', + '\u01D2': 'o', + '\u020D': 'o', + '\u020F': 'o', + '\u01A1': 'o', + '\u1EDD': 'o', + '\u1EDB': 'o', + '\u1EE1': 'o', + '\u1EDF': 'o', + '\u1EE3': 'o', + '\u1ECD': 'o', + '\u1ED9': 'o', + '\u01EB': 'o', + '\u01ED': 'o', + '\u00F8': 'o', + '\u01FF': 'o', + '\u0254': 'o', + '\uA74B': 'o', + '\uA74D': 'o', + '\u0275': 'o', + '\u01A3': 'oi', + '\u0223': 'ou', + '\uA74F': 'oo', + '\u24DF': 'p', + '\uFF50': 'p', + '\u1E55': 'p', + '\u1E57': 'p', + '\u01A5': 'p', + '\u1D7D': 'p', + '\uA751': 'p', + '\uA753': 'p', + '\uA755': 'p', + '\u24E0': 'q', + '\uFF51': 'q', + '\u024B': 'q', + '\uA757': 'q', + '\uA759': 'q', + '\u24E1': 'r', + '\uFF52': 'r', + '\u0155': 'r', + '\u1E59': 'r', + '\u0159': 'r', + '\u0211': 'r', + '\u0213': 'r', + '\u1E5B': 'r', + '\u1E5D': 'r', + '\u0157': 'r', + '\u1E5F': 'r', + '\u024D': 'r', + '\u027D': 'r', + '\uA75B': 'r', + '\uA7A7': 'r', + '\uA783': 'r', + '\u24E2': 's', + '\uFF53': 's', + '\u00DF': 's', + '\u015B': 's', + '\u1E65': 's', + '\u015D': 's', + '\u1E61': 's', + '\u0161': 's', + '\u1E67': 's', + '\u1E63': 's', + '\u1E69': 's', + '\u0219': 's', + '\u015F': 's', + '\u023F': 's', + '\uA7A9': 's', + '\uA785': 's', + '\u1E9B': 's', + '\u24E3': 't', + '\uFF54': 't', + '\u1E6B': 't', + '\u1E97': 't', + '\u0165': 't', + '\u1E6D': 't', + '\u021B': 't', + '\u0163': 't', + '\u1E71': 't', + '\u1E6F': 't', + '\u0167': 't', + '\u01AD': 't', + '\u0288': 't', + '\u2C66': 't', + '\uA787': 't', + '\uA729': 'tz', + '\u24E4': 'u', + '\uFF55': 'u', + '\u00F9': 'u', + '\u00FA': 'u', + '\u00FB': 'u', + '\u0169': 'u', + '\u1E79': 'u', + '\u016B': 'u', + '\u1E7B': 'u', + '\u016D': 'u', + '\u00FC': 'u', + '\u01DC': 'u', + '\u01D8': 'u', + '\u01D6': 'u', + '\u01DA': 'u', + '\u1EE7': 'u', + '\u016F': 'u', + '\u0171': 'u', + '\u01D4': 'u', + '\u0215': 'u', + '\u0217': 'u', + '\u01B0': 'u', + '\u1EEB': 'u', + '\u1EE9': 'u', + '\u1EEF': 'u', + '\u1EED': 'u', + '\u1EF1': 'u', + '\u1EE5': 'u', + '\u1E73': 'u', + '\u0173': 'u', + '\u1E77': 'u', + '\u1E75': 'u', + '\u0289': 'u', + '\u24E5': 'v', + '\uFF56': 'v', + '\u1E7D': 'v', + '\u1E7F': 'v', + '\u028B': 'v', + '\uA75F': 'v', + '\u028C': 'v', + '\uA761': 'vy', + '\u24E6': 'w', + '\uFF57': 'w', + '\u1E81': 'w', + '\u1E83': 'w', + '\u0175': 'w', + '\u1E87': 'w', + '\u1E85': 'w', + '\u1E98': 'w', + '\u1E89': 'w', + '\u2C73': 'w', + '\u24E7': 'x', + '\uFF58': 'x', + '\u1E8B': 'x', + '\u1E8D': 'x', + '\u24E8': 'y', + '\uFF59': 'y', + '\u1EF3': 'y', + '\u00FD': 'y', + '\u0177': 'y', + '\u1EF9': 'y', + '\u0233': 'y', + '\u1E8F': 'y', + '\u00FF': 'y', + '\u1EF7': 'y', + '\u1E99': 'y', + '\u1EF5': 'y', + '\u01B4': 'y', + '\u024F': 'y', + '\u1EFF': 'y', + '\u24E9': 'z', + '\uFF5A': 'z', + '\u017A': 'z', + '\u1E91': 'z', + '\u017C': 'z', + '\u017E': 'z', + '\u1E93': 'z', + '\u1E95': 'z', + '\u01B6': 'z', + '\u0225': 'z', + '\u0240': 'z', + '\u2C6C': 'z', + '\uA763': 'z', + '\u0386': '\u0391', + '\u0388': '\u0395', + '\u0389': '\u0397', + '\u038A': '\u0399', + '\u03AA': '\u0399', + '\u038C': '\u039F', + '\u038E': '\u03A5', + '\u03AB': '\u03A5', + '\u038F': '\u03A9', + '\u03AC': '\u03B1', + '\u03AD': '\u03B5', + '\u03AE': '\u03B7', + '\u03AF': '\u03B9', + '\u03CA': '\u03B9', + '\u0390': '\u03B9', + '\u03CC': '\u03BF', + '\u03CD': '\u03C5', + '\u03CB': '\u03C5', + '\u03B0': '\u03C5', + '\u03C9': '\u03C9', + '\u03C2': '\u03C3' + }; + + return diacritics; +}); + +S2.define('select2/data/base',[ + '../utils' +], function (Utils) { + function BaseAdapter ($element, options) { + BaseAdapter.__super__.constructor.call(this); + } + + Utils.Extend(BaseAdapter, Utils.Observable); + + BaseAdapter.prototype.current = function (callback) { + throw new Error('The `current` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.query = function (params, callback) { + throw new Error('The `query` method must be defined in child classes.'); + }; + + BaseAdapter.prototype.bind = function (container, $container) { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.destroy = function () { + // Can be implemented in subclasses + }; + + BaseAdapter.prototype.generateResultId = function (container, data) { + var id = container.id + '-result-'; + + id += Utils.generateChars(4); + + if (data.id != null) { + id += '-' + data.id.toString(); + } else { + id += '-' + Utils.generateChars(4); + } + return id; + }; + + return BaseAdapter; +}); + +S2.define('select2/data/select',[ + './base', + '../utils', + 'jquery' +], function (BaseAdapter, Utils, $) { + function SelectAdapter ($element, options) { + this.$element = $element; + this.options = options; + + SelectAdapter.__super__.constructor.call(this); + } + + Utils.Extend(SelectAdapter, BaseAdapter); + + SelectAdapter.prototype.current = function (callback) { + var data = []; + var self = this; + + this.$element.find(':selected').each(function () { + var $option = $(this); + + var option = self.item($option); + + data.push(option); + }); + + callback(data); + }; + + SelectAdapter.prototype.select = function (data) { + var self = this; + + data.selected = true; + + // If data.element is a DOM node, use it instead + if ($(data.element).is('option')) { + data.element.selected = true; + + this.$element.trigger('change'); + + return; + } + + if (this.$element.prop('multiple')) { + this.current(function (currentData) { + var val = []; + + data = [data]; + data.push.apply(data, currentData); + + for (var d = 0; d < data.length; d++) { + var id = data[d].id; + + if ($.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + self.$element.trigger('change'); + }); + } else { + var val = data.id; + + this.$element.val(val); + this.$element.trigger('change'); + } + }; + + SelectAdapter.prototype.unselect = function (data) { + var self = this; + + if (!this.$element.prop('multiple')) { + return; + } + + data.selected = false; + + if ($(data.element).is('option')) { + data.element.selected = false; + + this.$element.trigger('change'); + + return; + } + + this.current(function (currentData) { + var val = []; + + for (var d = 0; d < currentData.length; d++) { + var id = currentData[d].id; + + if (id !== data.id && $.inArray(id, val) === -1) { + val.push(id); + } + } + + self.$element.val(val); + + self.$element.trigger('change'); + }); + }; + + SelectAdapter.prototype.bind = function (container, $container) { + var self = this; + + this.container = container; + + container.on('select', function (params) { + self.select(params.data); + }); + + container.on('unselect', function (params) { + self.unselect(params.data); + }); + }; + + SelectAdapter.prototype.destroy = function () { + // Remove anything added to child elements + this.$element.find('*').each(function () { + // Remove any custom data set by Select2 + $.removeData(this, 'data'); + }); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + var $options = this.$element.children(); + + $options.each(function () { + var $option = $(this); + + if (!$option.is('option') && !$option.is('optgroup')) { + return; + } + + var option = self.item($option); + + var matches = self.matches(params, option); + + if (matches !== null) { + data.push(matches); + } + }); + + callback({ + results: data + }); + }; + + SelectAdapter.prototype.addOptions = function ($options) { + Utils.appendMany(this.$element, $options); + }; + + SelectAdapter.prototype.option = function (data) { + var option; + + if (data.children) { + option = document.createElement('optgroup'); + option.label = data.text; + } else { + option = document.createElement('option'); + + if (option.textContent !== undefined) { + option.textContent = data.text; + } else { + option.innerText = data.text; + } + } + + if (data.id) { + option.value = data.id; + } + + if (data.disabled) { + option.disabled = true; + } + + if (data.selected) { + option.selected = true; + } + + if (data.title) { + option.title = data.title; + } + + var $option = $(option); + + var normalizedData = this._normalizeItem(data); + normalizedData.element = option; + + // Override the option's data with the combined data + $.data(option, 'data', normalizedData); + + return $option; + }; + + SelectAdapter.prototype.item = function ($option) { + var data = {}; + + data = $.data($option[0], 'data'); + + if (data != null) { + return data; + } + + if ($option.is('option')) { + data = { + id: $option.val(), + text: $option.text(), + disabled: $option.prop('disabled'), + selected: $option.prop('selected'), + title: $option.prop('title') + }; + } else if ($option.is('optgroup')) { + data = { + text: $option.prop('label'), + children: [], + title: $option.prop('title') + }; + + var $children = $option.children('option'); + var children = []; + + for (var c = 0; c < $children.length; c++) { + var $child = $($children[c]); + + var child = this.item($child); + + children.push(child); + } + + data.children = children; + } + + data = this._normalizeItem(data); + data.element = $option[0]; + + $.data($option[0], 'data', data); + + return data; + }; + + SelectAdapter.prototype._normalizeItem = function (item) { + if (!$.isPlainObject(item)) { + item = { + id: item, + text: item + }; + } + + item = $.extend({}, { + text: '' + }, item); + + var defaults = { + selected: false, + disabled: false + }; + + if (item.id != null) { + item.id = item.id.toString(); + } + + if (item.text != null) { + item.text = item.text.toString(); + } + + if (item._resultId == null && item.id && this.container != null) { + item._resultId = this.generateResultId(this.container, item); + } + + return $.extend({}, defaults, item); + }; + + SelectAdapter.prototype.matches = function (params, data) { + var matcher = this.options.get('matcher'); + + return matcher(params, data); + }; + + return SelectAdapter; +}); + +S2.define('select2/data/array',[ + './select', + '../utils', + 'jquery' +], function (SelectAdapter, Utils, $) { + function ArrayAdapter ($element, options) { + var data = options.get('data') || []; + + ArrayAdapter.__super__.constructor.call(this, $element, options); + + this.addOptions(this.convertToOptions(data)); + } + + Utils.Extend(ArrayAdapter, SelectAdapter); + + ArrayAdapter.prototype.select = function (data) { + var $option = this.$element.find('option').filter(function (i, elm) { + return elm.value == data.id.toString(); + }); + + if ($option.length === 0) { + $option = this.option(data); + + this.addOptions($option); + } + + ArrayAdapter.__super__.select.call(this, data); + }; + + ArrayAdapter.prototype.convertToOptions = function (data) { + var self = this; + + var $existing = this.$element.find('option'); + var existingIds = $existing.map(function () { + return self.item($(this)).id; + }).get(); + + var $options = []; + + // Filter out all items except for the one passed in the argument + function onlyItem (item) { + return function () { + return $(this).val() == item.id; + }; + } + + for (var d = 0; d < data.length; d++) { + var item = this._normalizeItem(data[d]); + + // Skip items which were pre-loaded, only merge the data + if ($.inArray(item.id, existingIds) >= 0) { + var $existingOption = $existing.filter(onlyItem(item)); + + var existingData = this.item($existingOption); + var newData = $.extend(true, {}, item, existingData); + + var $newOption = this.option(newData); + + $existingOption.replaceWith($newOption); + + continue; + } + + var $option = this.option(item); + + if (item.children) { + var $children = this.convertToOptions(item.children); + + Utils.appendMany($option, $children); + } + + $options.push($option); + } + + return $options; + }; + + return ArrayAdapter; +}); + +S2.define('select2/data/ajax',[ + './array', + '../utils', + 'jquery' +], function (ArrayAdapter, Utils, $) { + function AjaxAdapter ($element, options) { + this.ajaxOptions = this._applyDefaults(options.get('ajax')); + + if (this.ajaxOptions.processResults != null) { + this.processResults = this.ajaxOptions.processResults; + } + + AjaxAdapter.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(AjaxAdapter, ArrayAdapter); + + AjaxAdapter.prototype._applyDefaults = function (options) { + var defaults = { + data: function (params) { + return $.extend({}, params, { + q: params.term + }); + }, + transport: function (params, success, failure) { + var $request = $.ajax(params); + + $request.then(success); + $request.fail(failure); + + return $request; + } + }; + + return $.extend({}, defaults, options, true); + }; + + AjaxAdapter.prototype.processResults = function (results) { + return results; + }; + + AjaxAdapter.prototype.query = function (params, callback) { + var matches = []; + var self = this; + + if (this._request != null) { + // JSONP requests cannot always be aborted + if ($.isFunction(this._request.abort)) { + this._request.abort(); + } + + this._request = null; + } + + var options = $.extend({ + type: 'GET' + }, this.ajaxOptions); + + if (typeof options.url === 'function') { + options.url = options.url.call(this.$element, params); + } + + if (typeof options.data === 'function') { + options.data = options.data.call(this.$element, params); + } + + function request () { + var $request = options.transport(options, function (data) { + var results = self.processResults(data, params); + + if (self.options.get('debug') && window.console && console.error) { + // Check to make sure that the response included a `results` key. + if (!results || !results.results || !$.isArray(results.results)) { + console.error( + 'Select2: The AJAX results did not return an array in the ' + + '`results` key of the response.' + ); + } + } + + callback(results); + }, function () { + // Attempt to detect if a request was aborted + // Only works if the transport exposes a status property + if ($request.status && $request.status === '0') { + return; + } + + self.trigger('results:message', { + message: 'errorLoading' + }); + }); + + self._request = $request; + } + + if (this.ajaxOptions.delay && params.term != null) { + if (this._queryTimeout) { + window.clearTimeout(this._queryTimeout); + } + + this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); + } else { + request(); + } + }; + + return AjaxAdapter; +}); + +S2.define('select2/data/tags',[ + 'jquery' +], function ($) { + function Tags (decorated, $element, options) { + var tags = options.get('tags'); + + var createTag = options.get('createTag'); + + if (createTag !== undefined) { + this.createTag = createTag; + } + + var insertTag = options.get('insertTag'); + + if (insertTag !== undefined) { + this.insertTag = insertTag; + } + + decorated.call(this, $element, options); + + if ($.isArray(tags)) { + for (var t = 0; t < tags.length; t++) { + var tag = tags[t]; + var item = this._normalizeItem(tag); + + var $option = this.option(item); + + this.$element.append($option); + } + } + } + + Tags.prototype.query = function (decorated, params, callback) { + var self = this; + + this._removeOldTags(); + + if (params.term == null || params.page != null) { + decorated.call(this, params, callback); + return; + } + + function wrapper (obj, child) { + var data = obj.results; + + for (var i = 0; i < data.length; i++) { + var option = data[i]; + + var checkChildren = ( + option.children != null && + !wrapper({ + results: option.children + }, true) + ); + + var checkText = option.text === params.term; + + if (checkText || checkChildren) { + if (child) { + return false; + } + + obj.data = data; + callback(obj); + + return; + } + } + + if (child) { + return true; + } + + var tag = self.createTag(params); + + if (tag != null) { + var $option = self.option(tag); + $option.attr('data-select2-tag', true); + + self.addOptions([$option]); + + self.insertTag(data, tag); + } + + obj.results = data; + + callback(obj); + } + + decorated.call(this, params, wrapper); + }; + + Tags.prototype.createTag = function (decorated, params) { + var term = $.trim(params.term); + + if (term === '') { + return null; + } + + return { + id: term, + text: term + }; + }; + + Tags.prototype.insertTag = function (_, data, tag) { + data.unshift(tag); + }; + + Tags.prototype._removeOldTags = function (_) { + var tag = this._lastTag; + + var $options = this.$element.find('option[data-select2-tag]'); + + $options.each(function () { + if (this.selected) { + return; + } + + $(this).remove(); + }); + }; + + return Tags; +}); + +S2.define('select2/data/tokenizer',[ + 'jquery' +], function ($) { + function Tokenizer (decorated, $element, options) { + var tokenizer = options.get('tokenizer'); + + if (tokenizer !== undefined) { + this.tokenizer = tokenizer; + } + + decorated.call(this, $element, options); + } + + Tokenizer.prototype.bind = function (decorated, container, $container) { + decorated.call(this, container, $container); + + this.$search = container.dropdown.$search || container.selection.$search || + $container.find('.select2-search__field'); + }; + + Tokenizer.prototype.query = function (decorated, params, callback) { + var self = this; + + function createAndSelect (data) { + // Normalize the data object so we can use it for checks + var item = self._normalizeItem(data); + + // Check if the data object already exists as a tag + // Select it if it doesn't + var $existingOptions = self.$element.find('option').filter(function () { + return $(this).val() === item.id; + }); + + // If an existing option wasn't found for it, create the option + if (!$existingOptions.length) { + var $option = self.option(item); + $option.attr('data-select2-tag', true); + + self._removeOldTags(); + self.addOptions([$option]); + } + + // Select the item, now that we know there is an option for it + select(item); + } + + function select (data) { + self.trigger('select', { + data: data + }); + } + + params.term = params.term || ''; + + var tokenData = this.tokenizer(params, this.options, createAndSelect); + + if (tokenData.term !== params.term) { + // Replace the search term if we have the search box + if (this.$search.length) { + this.$search.val(tokenData.term); + this.$search.focus(); + } + + params.term = tokenData.term; + } + + decorated.call(this, params, callback); + }; + + Tokenizer.prototype.tokenizer = function (_, params, options, callback) { + var separators = options.get('tokenSeparators') || []; + var term = params.term; + var i = 0; + + var createTag = this.createTag || function (params) { + return { + id: params.term, + text: params.term + }; + }; + + while (i < term.length) { + var termChar = term[i]; + + if ($.inArray(termChar, separators) === -1) { + i++; + + continue; + } + + var part = term.substr(0, i); + var partParams = $.extend({}, params, { + term: part + }); + + var data = createTag(partParams); + + if (data == null) { + i++; + continue; + } + + callback(data); + + // Reset the term to not include the tokenized portion + term = term.substr(i + 1) || ''; + i = 0; + } + + return { + term: term + }; + }; + + return Tokenizer; +}); + +S2.define('select2/data/minimumInputLength',[ + +], function () { + function MinimumInputLength (decorated, $e, options) { + this.minimumInputLength = options.get('minimumInputLength'); + + decorated.call(this, $e, options); + } + + MinimumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (params.term.length < this.minimumInputLength) { + this.trigger('results:message', { + message: 'inputTooShort', + args: { + minimum: this.minimumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MinimumInputLength; +}); + +S2.define('select2/data/maximumInputLength',[ + +], function () { + function MaximumInputLength (decorated, $e, options) { + this.maximumInputLength = options.get('maximumInputLength'); + + decorated.call(this, $e, options); + } + + MaximumInputLength.prototype.query = function (decorated, params, callback) { + params.term = params.term || ''; + + if (this.maximumInputLength > 0 && + params.term.length > this.maximumInputLength) { + this.trigger('results:message', { + message: 'inputTooLong', + args: { + maximum: this.maximumInputLength, + input: params.term, + params: params + } + }); + + return; + } + + decorated.call(this, params, callback); + }; + + return MaximumInputLength; +}); + +S2.define('select2/data/maximumSelectionLength',[ + +], function (){ + function MaximumSelectionLength (decorated, $e, options) { + this.maximumSelectionLength = options.get('maximumSelectionLength'); + + decorated.call(this, $e, options); + } + + MaximumSelectionLength.prototype.query = + function (decorated, params, callback) { + var self = this; + + this.current(function (currentData) { + var count = currentData != null ? currentData.length : 0; + if (self.maximumSelectionLength > 0 && + count >= self.maximumSelectionLength) { + self.trigger('results:message', { + message: 'maximumSelected', + args: { + maximum: self.maximumSelectionLength + } + }); + return; + } + decorated.call(self, params, callback); + }); + }; + + return MaximumSelectionLength; +}); + +S2.define('select2/dropdown',[ + 'jquery', + './utils' +], function ($, Utils) { + function Dropdown ($element, options) { + this.$element = $element; + this.options = options; + + Dropdown.__super__.constructor.call(this); + } + + Utils.Extend(Dropdown, Utils.Observable); + + Dropdown.prototype.render = function () { + var $dropdown = $( + '' + + '' + + '' + ); + + $dropdown.attr('dir', this.options.get('dir')); + + this.$dropdown = $dropdown; + + return $dropdown; + }; + + Dropdown.prototype.bind = function () { + // Should be implemented in subclasses + }; + + Dropdown.prototype.position = function ($dropdown, $container) { + // Should be implmented in subclasses + }; + + Dropdown.prototype.destroy = function () { + // Remove the dropdown from the DOM + this.$dropdown.remove(); + }; + + return Dropdown; +}); + +S2.define('select2/dropdown/search',[ + 'jquery', + '../utils' +], function ($, Utils) { + function Search () { } + + Search.prototype.render = function (decorated) { + var $rendered = decorated.call(this); + + var $search = $( + '' + + '' + + '' + ); + + this.$searchContainer = $search; + this.$search = $search.find('input'); + + $rendered.prepend($search); + + return $rendered; + }; + + Search.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + this.$search.on('keydown', function (evt) { + self.trigger('keypress', evt); + + self._keyUpPrevented = evt.isDefaultPrevented(); + }); + + // Workaround for browsers which do not support the `input` event + // This will prevent double-triggering of events for browsers which support + // both the `keyup` and `input` events. + this.$search.on('input', function (evt) { + // Unbind the duplicated `keyup` event + $(this).off('keyup'); + }); + + this.$search.on('keyup input', function (evt) { + self.handleSearch(evt); + }); + + container.on('open', function () { + self.$search.attr('tabindex', 0); + + self.$search.focus(); + + window.setTimeout(function () { + self.$search.focus(); + }, 0); + }); + + container.on('close', function () { + self.$search.attr('tabindex', -1); + + self.$search.val(''); + }); + + container.on('focus', function () { + if (container.isOpen()) { + self.$search.focus(); + } + }); + + container.on('results:all', function (params) { + if (params.query.term == null || params.query.term === '') { + var showSearch = self.showSearch(params); + + if (showSearch) { + self.$searchContainer.removeClass('select2-search--hide'); + } else { + self.$searchContainer.addClass('select2-search--hide'); + } + } + }); + }; + + Search.prototype.handleSearch = function (evt) { + if (!this._keyUpPrevented) { + var input = this.$search.val(); + + this.trigger('query', { + term: input + }); + } + + this._keyUpPrevented = false; + }; + + Search.prototype.showSearch = function (_, params) { + return true; + }; + + return Search; +}); + +S2.define('select2/dropdown/hidePlaceholder',[ + +], function () { + function HidePlaceholder (decorated, $element, options, dataAdapter) { + this.placeholder = this.normalizePlaceholder(options.get('placeholder')); + + decorated.call(this, $element, options, dataAdapter); + } + + HidePlaceholder.prototype.append = function (decorated, data) { + data.results = this.removePlaceholder(data.results); + + decorated.call(this, data); + }; + + HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { + if (typeof placeholder === 'string') { + placeholder = { + id: '', + text: placeholder + }; + } + + return placeholder; + }; + + HidePlaceholder.prototype.removePlaceholder = function (_, data) { + var modifiedData = data.slice(0); + + for (var d = data.length - 1; d >= 0; d--) { + var item = data[d]; + + if (this.placeholder.id === item.id) { + modifiedData.splice(d, 1); + } + } + + return modifiedData; + }; + + return HidePlaceholder; +}); + +S2.define('select2/dropdown/infiniteScroll',[ + 'jquery' +], function ($) { + function InfiniteScroll (decorated, $element, options, dataAdapter) { + this.lastParams = {}; + + decorated.call(this, $element, options, dataAdapter); + + this.$loadingMore = this.createLoadingMore(); + this.loading = false; + } + + InfiniteScroll.prototype.append = function (decorated, data) { + this.$loadingMore.remove(); + this.loading = false; + + decorated.call(this, data); + + if (this.showLoadingMore(data)) { + this.$results.append(this.$loadingMore); + } + }; + + InfiniteScroll.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('query', function (params) { + self.lastParams = params; + self.loading = true; + }); + + container.on('query:append', function (params) { + self.lastParams = params; + self.loading = true; + }); + + this.$results.on('scroll', function () { + var isLoadMoreVisible = $.contains( + document.documentElement, + self.$loadingMore[0] + ); + + if (self.loading || !isLoadMoreVisible) { + return; + } + + var currentOffset = self.$results.offset().top + + self.$results.outerHeight(false); + var loadingMoreOffset = self.$loadingMore.offset().top + + self.$loadingMore.outerHeight(false); + + if (currentOffset + 50 >= loadingMoreOffset) { + self.loadMore(); + } + }); + }; + + InfiniteScroll.prototype.loadMore = function () { + this.loading = true; + + var params = $.extend({}, {page: 1}, this.lastParams); + + params.page++; + + this.trigger('query:append', params); + }; + + InfiniteScroll.prototype.showLoadingMore = function (_, data) { + return data.pagination && data.pagination.more; + }; + + InfiniteScroll.prototype.createLoadingMore = function () { + var $option = $( + '
      • ' + ); + + var message = this.options.get('translations').get('loadingMore'); + + $option.html(message(this.lastParams)); + + return $option; + }; + + return InfiniteScroll; +}); + +S2.define('select2/dropdown/attachBody',[ + 'jquery', + '../utils' +], function ($, Utils) { + function AttachBody (decorated, $element, options) { + this.$dropdownParent = options.get('dropdownParent') || $(document.body); + + decorated.call(this, $element, options); + } + + AttachBody.prototype.bind = function (decorated, container, $container) { + var self = this; + + var setupResultsEvents = false; + + decorated.call(this, container, $container); + + container.on('open', function () { + self._showDropdown(); + self._attachPositioningHandler(container); + + if (!setupResultsEvents) { + setupResultsEvents = true; + + container.on('results:all', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + + container.on('results:append', function () { + self._positionDropdown(); + self._resizeDropdown(); + }); + } + }); + + container.on('close', function () { + self._hideDropdown(); + self._detachPositioningHandler(container); + }); + + this.$dropdownContainer.on('mousedown', function (evt) { + evt.stopPropagation(); + }); + }; + + AttachBody.prototype.destroy = function (decorated) { + decorated.call(this); + + this.$dropdownContainer.remove(); + }; + + AttachBody.prototype.position = function (decorated, $dropdown, $container) { + // Clone all of the container classes + $dropdown.attr('class', $container.attr('class')); + + $dropdown.removeClass('select2'); + $dropdown.addClass('select2-container--open'); + + $dropdown.css({ + position: 'absolute', + top: -999999 + }); + + this.$container = $container; + }; + + AttachBody.prototype.render = function (decorated) { + var $container = $(''); + + var $dropdown = decorated.call(this); + $container.append($dropdown); + + this.$dropdownContainer = $container; + + return $container; + }; + + AttachBody.prototype._hideDropdown = function (decorated) { + this.$dropdownContainer.detach(); + }; + + AttachBody.prototype._attachPositioningHandler = + function (decorated, container) { + var self = this; + + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.each(function () { + $(this).data('select2-scroll-position', { + x: $(this).scrollLeft(), + y: $(this).scrollTop() + }); + }); + + $watchers.on(scrollEvent, function (ev) { + var position = $(this).data('select2-scroll-position'); + $(this).scrollTop(position.y); + }); + + $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, + function (e) { + self._positionDropdown(); + self._resizeDropdown(); + }); + }; + + AttachBody.prototype._detachPositioningHandler = + function (decorated, container) { + var scrollEvent = 'scroll.select2.' + container.id; + var resizeEvent = 'resize.select2.' + container.id; + var orientationEvent = 'orientationchange.select2.' + container.id; + + var $watchers = this.$container.parents().filter(Utils.hasScroll); + $watchers.off(scrollEvent); + + $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); + }; + + AttachBody.prototype._positionDropdown = function () { + var $window = $(window); + + var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above'); + var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below'); + + var newDirection = null; + + var offset = this.$container.offset(); + + offset.bottom = offset.top + this.$container.outerHeight(false); + + var container = { + height: this.$container.outerHeight(false) + }; + + container.top = offset.top; + container.bottom = offset.top + container.height; + + var dropdown = { + height: this.$dropdown.outerHeight(false) + }; + + var viewport = { + top: $window.scrollTop(), + bottom: $window.scrollTop() + $window.height() + }; + + var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); + var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); + + var css = { + left: offset.left, + top: container.bottom + }; + + // Determine what the parent element is to use for calciulating the offset + var $offsetParent = this.$dropdownParent; + + // For statically positoned elements, we need to get the element + // that is determining the offset + if ($offsetParent.css('position') === 'static') { + $offsetParent = $offsetParent.offsetParent(); + } + + var parentOffset = $offsetParent.offset(); + + css.top -= parentOffset.top; + css.left -= parentOffset.left; + + if (!isCurrentlyAbove && !isCurrentlyBelow) { + newDirection = 'below'; + } + + if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { + newDirection = 'above'; + } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { + newDirection = 'below'; + } + + if (newDirection == 'above' || + (isCurrentlyAbove && newDirection !== 'below')) { + css.top = container.top - parentOffset.top - dropdown.height; + } + + if (newDirection != null) { + this.$dropdown + .removeClass('select2-dropdown--below select2-dropdown--above') + .addClass('select2-dropdown--' + newDirection); + this.$container + .removeClass('select2-container--below select2-container--above') + .addClass('select2-container--' + newDirection); + } + + this.$dropdownContainer.css(css); + }; + + AttachBody.prototype._resizeDropdown = function () { + var css = { + width: this.$container.outerWidth(false) + 'px' + }; + + if (this.options.get('dropdownAutoWidth')) { + css.minWidth = css.width; + css.position = 'relative'; + css.width = 'auto'; + } + + this.$dropdown.css(css); + }; + + AttachBody.prototype._showDropdown = function (decorated) { + this.$dropdownContainer.appendTo(this.$dropdownParent); + + this._positionDropdown(); + this._resizeDropdown(); + }; + + return AttachBody; +}); + +S2.define('select2/dropdown/minimumResultsForSearch',[ + +], function () { + function countResults (data) { + var count = 0; + + for (var d = 0; d < data.length; d++) { + var item = data[d]; + + if (item.children) { + count += countResults(item.children); + } else { + count++; + } + } + + return count; + } + + function MinimumResultsForSearch (decorated, $element, options, dataAdapter) { + this.minimumResultsForSearch = options.get('minimumResultsForSearch'); + + if (this.minimumResultsForSearch < 0) { + this.minimumResultsForSearch = Infinity; + } + + decorated.call(this, $element, options, dataAdapter); + } + + MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { + if (countResults(params.data.results) < this.minimumResultsForSearch) { + return false; + } + + return decorated.call(this, params); + }; + + return MinimumResultsForSearch; +}); + +S2.define('select2/dropdown/selectOnClose',[ + +], function () { + function SelectOnClose () { } + + SelectOnClose.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('close', function (params) { + self._handleSelectOnClose(params); + }); + }; + + SelectOnClose.prototype._handleSelectOnClose = function (_, params) { + if (params && params.originalSelect2Event != null) { + var event = params.originalSelect2Event; + + // Don't select an item if the close event was triggered from a select or + // unselect event + if (event._type === 'select' || event._type === 'unselect') { + return; + } + } + + var $highlightedResults = this.getHighlightedResults(); + + // Only select highlighted results + if ($highlightedResults.length < 1) { + return; + } + + var data = $highlightedResults.data('data'); + + // Don't re-select already selected resulte + if ( + (data.element != null && data.element.selected) || + (data.element == null && data.selected) + ) { + return; + } + + this.trigger('select', { + data: data + }); + }; + + return SelectOnClose; +}); + +S2.define('select2/dropdown/closeOnSelect',[ + +], function () { + function CloseOnSelect () { } + + CloseOnSelect.prototype.bind = function (decorated, container, $container) { + var self = this; + + decorated.call(this, container, $container); + + container.on('select', function (evt) { + self._selectTriggered(evt); + }); + + container.on('unselect', function (evt) { + self._selectTriggered(evt); + }); + }; + + CloseOnSelect.prototype._selectTriggered = function (_, evt) { + var originalEvent = evt.originalEvent; + + // Don't close if the control key is being held + if (originalEvent && originalEvent.ctrlKey) { + return; + } + + this.trigger('close', { + originalEvent: originalEvent, + originalSelect2Event: evt + }); + }; + + return CloseOnSelect; +}); + +S2.define('select2/i18n/en',[],function () { + // English + return { + errorLoading: function () { + return 'The results could not be loaded.'; + }, + inputTooLong: function (args) { + var overChars = args.input.length - args.maximum; + + var message = 'Please delete ' + overChars + ' character'; + + if (overChars != 1) { + message += 's'; + } + + return message; + }, + inputTooShort: function (args) { + var remainingChars = args.minimum - args.input.length; + + var message = 'Please enter ' + remainingChars + ' or more characters'; + + return message; + }, + loadingMore: function () { + return 'Loading more results…'; + }, + maximumSelected: function (args) { + var message = 'You can only select ' + args.maximum + ' item'; + + if (args.maximum != 1) { + message += 's'; + } + + return message; + }, + noResults: function () { + return 'No results found'; + }, + searching: function () { + return 'Searching…'; + } + }; +}); + +S2.define('select2/defaults',[ + 'jquery', + 'require', + + './results', + + './selection/single', + './selection/multiple', + './selection/placeholder', + './selection/allowClear', + './selection/search', + './selection/eventRelay', + + './utils', + './translation', + './diacritics', + + './data/select', + './data/array', + './data/ajax', + './data/tags', + './data/tokenizer', + './data/minimumInputLength', + './data/maximumInputLength', + './data/maximumSelectionLength', + + './dropdown', + './dropdown/search', + './dropdown/hidePlaceholder', + './dropdown/infiniteScroll', + './dropdown/attachBody', + './dropdown/minimumResultsForSearch', + './dropdown/selectOnClose', + './dropdown/closeOnSelect', + + './i18n/en' +], function ($, require, + + ResultsList, + + SingleSelection, MultipleSelection, Placeholder, AllowClear, + SelectionSearch, EventRelay, + + Utils, Translation, DIACRITICS, + + SelectData, ArrayData, AjaxData, Tags, Tokenizer, + MinimumInputLength, MaximumInputLength, MaximumSelectionLength, + + Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, + AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, + + EnglishTranslation) { + function Defaults () { + this.reset(); + } + + Defaults.prototype.apply = function (options) { + options = $.extend(true, {}, this.defaults, options); + + if (options.dataAdapter == null) { + if (options.ajax != null) { + options.dataAdapter = AjaxData; + } else if (options.data != null) { + options.dataAdapter = ArrayData; + } else { + options.dataAdapter = SelectData; + } + + if (options.minimumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MinimumInputLength + ); + } + + if (options.maximumInputLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumInputLength + ); + } + + if (options.maximumSelectionLength > 0) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + MaximumSelectionLength + ); + } + + if (options.tags) { + options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); + } + + if (options.tokenSeparators != null || options.tokenizer != null) { + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Tokenizer + ); + } + + if (options.query != null) { + var Query = require(options.amdBase + 'compat/query'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + Query + ); + } + + if (options.initSelection != null) { + var InitSelection = require(options.amdBase + 'compat/initSelection'); + + options.dataAdapter = Utils.Decorate( + options.dataAdapter, + InitSelection + ); + } + } + + if (options.resultsAdapter == null) { + options.resultsAdapter = ResultsList; + + if (options.ajax != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + InfiniteScroll + ); + } + + if (options.placeholder != null) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + HidePlaceholder + ); + } + + if (options.selectOnClose) { + options.resultsAdapter = Utils.Decorate( + options.resultsAdapter, + SelectOnClose + ); + } + } + + if (options.dropdownAdapter == null) { + if (options.multiple) { + options.dropdownAdapter = Dropdown; + } else { + var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); + + options.dropdownAdapter = SearchableDropdown; + } + + if (options.minimumResultsForSearch !== 0) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + MinimumResultsForSearch + ); + } + + if (options.closeOnSelect) { + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + CloseOnSelect + ); + } + + if ( + options.dropdownCssClass != null || + options.dropdownCss != null || + options.adaptDropdownCssClass != null + ) { + var DropdownCSS = require(options.amdBase + 'compat/dropdownCss'); + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + DropdownCSS + ); + } + + options.dropdownAdapter = Utils.Decorate( + options.dropdownAdapter, + AttachBody + ); + } + + if (options.selectionAdapter == null) { + if (options.multiple) { + options.selectionAdapter = MultipleSelection; + } else { + options.selectionAdapter = SingleSelection; + } + + // Add the placeholder mixin if a placeholder was specified + if (options.placeholder != null) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + Placeholder + ); + } + + if (options.allowClear) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + AllowClear + ); + } + + if (options.multiple) { + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + SelectionSearch + ); + } + + if ( + options.containerCssClass != null || + options.containerCss != null || + options.adaptContainerCssClass != null + ) { + var ContainerCSS = require(options.amdBase + 'compat/containerCss'); + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + ContainerCSS + ); + } + + options.selectionAdapter = Utils.Decorate( + options.selectionAdapter, + EventRelay + ); + } + + if (typeof options.language === 'string') { + // Check if the language is specified with a region + if (options.language.indexOf('-') > 0) { + // Extract the region information if it is included + var languageParts = options.language.split('-'); + var baseLanguage = languageParts[0]; + + options.language = [options.language, baseLanguage]; + } else { + options.language = [options.language]; + } + } + + if ($.isArray(options.language)) { + var languages = new Translation(); + options.language.push('en'); + + var languageNames = options.language; + + for (var l = 0; l < languageNames.length; l++) { + var name = languageNames[l]; + var language = {}; + + try { + // Try to load it with the original name + language = Translation.loadPath(name); + } catch (e) { + try { + // If we couldn't load it, check if it wasn't the full path + name = this.defaults.amdLanguageBase + name; + language = Translation.loadPath(name); + } catch (ex) { + // The translation could not be loaded at all. Sometimes this is + // because of a configuration problem, other times this can be + // because of how Select2 helps load all possible translation files. + if (options.debug && window.console && console.warn) { + console.warn( + 'Select2: The language file for "' + name + '" could not be ' + + 'automatically loaded. A fallback will be used instead.' + ); + } + + continue; + } + } + + languages.extend(language); + } + + options.translations = languages; + } else { + var baseTranslation = Translation.loadPath( + this.defaults.amdLanguageBase + 'en' + ); + var customTranslation = new Translation(options.language); + + customTranslation.extend(baseTranslation); + + options.translations = customTranslation; + } + + return options; + }; + + Defaults.prototype.reset = function () { + function stripDiacritics (text) { + // Used 'uni range + named function' from http://jsperf.com/diacritics/18 + function match(a) { + return DIACRITICS[a] || a; + } + + return text.replace(/[^\u0000-\u007E]/g, match); + } + + function matcher (params, data) { + // Always return the object if there is nothing to compare + if ($.trim(params.term) === '') { + return data; + } + + // Do a recursive check for options with children + if (data.children && data.children.length > 0) { + // Clone the data object if there are children + // This is required as we modify the object to remove any non-matches + var match = $.extend(true, {}, data); + + // Check each child of the option + for (var c = data.children.length - 1; c >= 0; c--) { + var child = data.children[c]; + + var matches = matcher(params, child); + + // If there wasn't a match, remove the object in the array + if (matches == null) { + match.children.splice(c, 1); + } + } + + // If any children matched, return the new object + if (match.children.length > 0) { + return match; + } + + // If there were no matching children, check just the plain object + return matcher(params, match); + } + + var original = stripDiacritics(data.text).toUpperCase(); + var term = stripDiacritics(params.term).toUpperCase(); + + // Check if the text contains the term + if (original.indexOf(term) > -1) { + return data; + } + + // If it doesn't contain the term, don't return anything + return null; + } + + this.defaults = { + amdBase: './', + amdLanguageBase: './i18n/', + closeOnSelect: true, + debug: false, + dropdownAutoWidth: false, + escapeMarkup: Utils.escapeMarkup, + language: EnglishTranslation, + matcher: matcher, + minimumInputLength: 0, + maximumInputLength: 0, + maximumSelectionLength: 0, + minimumResultsForSearch: 0, + selectOnClose: false, + sorter: function (data) { + return data; + }, + templateResult: function (result) { + return result.text; + }, + templateSelection: function (selection) { + return selection.text; + }, + theme: 'default', + width: 'resolve' + }; + }; + + Defaults.prototype.set = function (key, value) { + var camelKey = $.camelCase(key); + + var data = {}; + data[camelKey] = value; + + var convertedData = Utils._convertData(data); + + $.extend(this.defaults, convertedData); + }; + + var defaults = new Defaults(); + + return defaults; +}); + +S2.define('select2/options',[ + 'require', + 'jquery', + './defaults', + './utils' +], function (require, $, Defaults, Utils) { + function Options (options, $element) { + this.options = options; + + if ($element != null) { + this.fromElement($element); + } + + this.options = Defaults.apply(this.options); + + if ($element && $element.is('input')) { + var InputCompat = require(this.get('amdBase') + 'compat/inputData'); + + this.options.dataAdapter = Utils.Decorate( + this.options.dataAdapter, + InputCompat + ); + } + } + + Options.prototype.fromElement = function ($e) { + var excludedData = ['select2']; + + if (this.options.multiple == null) { + this.options.multiple = $e.prop('multiple'); + } + + if (this.options.disabled == null) { + this.options.disabled = $e.prop('disabled'); + } + + if (this.options.language == null) { + if ($e.prop('lang')) { + this.options.language = $e.prop('lang').toLowerCase(); + } else if ($e.closest('[lang]').prop('lang')) { + this.options.language = $e.closest('[lang]').prop('lang'); + } + } + + if (this.options.dir == null) { + if ($e.prop('dir')) { + this.options.dir = $e.prop('dir'); + } else if ($e.closest('[dir]').prop('dir')) { + this.options.dir = $e.closest('[dir]').prop('dir'); + } else { + this.options.dir = 'ltr'; + } + } + + $e.prop('disabled', this.options.disabled); + $e.prop('multiple', this.options.multiple); + + if ($e.data('select2Tags')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-select2-tags` attribute has been changed to ' + + 'use the `data-data` and `data-tags="true"` attributes and will be ' + + 'removed in future versions of Select2.' + ); + } + + $e.data('data', $e.data('select2Tags')); + $e.data('tags', true); + } + + if ($e.data('ajaxUrl')) { + if (this.options.debug && window.console && console.warn) { + console.warn( + 'Select2: The `data-ajax-url` attribute has been changed to ' + + '`data-ajax--url` and support for the old attribute will be removed' + + ' in future versions of Select2.' + ); + } + + $e.attr('ajax--url', $e.data('ajaxUrl')); + $e.data('ajax--url', $e.data('ajaxUrl')); + } + + var dataset = {}; + + // Prefer the element's `dataset` attribute if it exists + // jQuery 1.x does not correctly handle data attributes with multiple dashes + if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { + dataset = $.extend(true, {}, $e[0].dataset, $e.data()); + } else { + dataset = $e.data(); + } + + var data = $.extend(true, {}, dataset); + + data = Utils._convertData(data); + + for (var key in data) { + if ($.inArray(key, excludedData) > -1) { + continue; + } + + if ($.isPlainObject(this.options[key])) { + $.extend(this.options[key], data[key]); + } else { + this.options[key] = data[key]; + } + } + + return this; + }; + + Options.prototype.get = function (key) { + return this.options[key]; + }; + + Options.prototype.set = function (key, val) { + this.options[key] = val; + }; + + return Options; +}); + +S2.define('select2/core',[ + 'jquery', + './options', + './utils', + './keys' +], function ($, Options, Utils, KEYS) { + var Select2 = function ($element, options) { + if ($element.data('select2') != null) { + $element.data('select2').destroy(); + } + + this.$element = $element; + + this.id = this._generateId($element); + + options = options || {}; + + this.options = new Options(options, $element); + + Select2.__super__.constructor.call(this); + + // Set up the tabindex + + var tabindex = $element.attr('tabindex') || 0; + $element.data('old-tabindex', tabindex); + $element.attr('tabindex', '-1'); + + // Set up containers and adapters + + var DataAdapter = this.options.get('dataAdapter'); + this.dataAdapter = new DataAdapter($element, this.options); + + var $container = this.render(); + + this._placeContainer($container); + + var SelectionAdapter = this.options.get('selectionAdapter'); + this.selection = new SelectionAdapter($element, this.options); + this.$selection = this.selection.render(); + + this.selection.position(this.$selection, $container); + + var DropdownAdapter = this.options.get('dropdownAdapter'); + this.dropdown = new DropdownAdapter($element, this.options); + this.$dropdown = this.dropdown.render(); + + this.dropdown.position(this.$dropdown, $container); + + var ResultsAdapter = this.options.get('resultsAdapter'); + this.results = new ResultsAdapter($element, this.options, this.dataAdapter); + this.$results = this.results.render(); + + this.results.position(this.$results, this.$dropdown); + + // Bind events + + var self = this; + + // Bind the container to all of the adapters + this._bindAdapters(); + + // Register any DOM event handlers + this._registerDomEvents(); + + // Register any internal event handlers + this._registerDataEvents(); + this._registerSelectionEvents(); + this._registerDropdownEvents(); + this._registerResultsEvents(); + this._registerEvents(); + + // Set the initial state + this.dataAdapter.current(function (initialData) { + self.trigger('selection:update', { + data: initialData + }); + }); + + // Hide the original select + $element.addClass('select2-hidden-accessible'); + $element.attr('aria-hidden', 'true'); + + // Synchronize any monitored attributes + this._syncAttributes(); + + $element.data('select2', this); + }; + + Utils.Extend(Select2, Utils.Observable); + + Select2.prototype._generateId = function ($element) { + var id = ''; + + if ($element.attr('id') != null) { + id = $element.attr('id'); + } else if ($element.attr('name') != null) { + id = $element.attr('name') + '-' + Utils.generateChars(2); + } else { + id = Utils.generateChars(4); + } + + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = 'select2-' + id; + + return id; + }; + + Select2.prototype._placeContainer = function ($container) { + $container.insertAfter(this.$element); + + var width = this._resolveWidth(this.$element, this.options.get('width')); + + if (width != null) { + $container.css('width', width); + } + }; + + Select2.prototype._resolveWidth = function ($element, method) { + var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; + + if (method == 'resolve') { + var styleWidth = this._resolveWidth($element, 'style'); + + if (styleWidth != null) { + return styleWidth; + } + + return this._resolveWidth($element, 'element'); + } + + if (method == 'element') { + var elementWidth = $element.outerWidth(false); + + if (elementWidth <= 0) { + return 'auto'; + } + + return elementWidth + 'px'; + } + + if (method == 'style') { + var style = $element.attr('style'); + + if (typeof(style) !== 'string') { + return null; + } + + var attrs = style.split(';'); + + for (var i = 0, l = attrs.length; i < l; i = i + 1) { + var attr = attrs[i].replace(/\s/g, ''); + var matches = attr.match(WIDTH); + + if (matches !== null && matches.length >= 1) { + return matches[1]; + } + } + + return null; + } + + return method; + }; + + Select2.prototype._bindAdapters = function () { + this.dataAdapter.bind(this, this.$container); + this.selection.bind(this, this.$container); + + this.dropdown.bind(this, this.$container); + this.results.bind(this, this.$container); + }; + + Select2.prototype._registerDomEvents = function () { + var self = this; + + this.$element.on('change.select2', function () { + self.dataAdapter.current(function (data) { + self.trigger('selection:update', { + data: data + }); + }); + }); + + this.$element.on('focus.select2', function (evt) { + self.trigger('focus', evt); + }); + + this._syncA = Utils.bind(this._syncAttributes, this); + this._syncS = Utils.bind(this._syncSubtree, this); + + if (this.$element[0].attachEvent) { + this.$element[0].attachEvent('onpropertychange', this._syncA); + } + + var observer = window.MutationObserver || + window.WebKitMutationObserver || + window.MozMutationObserver + ; + + if (observer != null) { + this._observer = new observer(function (mutations) { + $.each(mutations, self._syncA); + $.each(mutations, self._syncS); + }); + this._observer.observe(this.$element[0], { + attributes: true, + childList: true, + subtree: false + }); + } else if (this.$element[0].addEventListener) { + this.$element[0].addEventListener( + 'DOMAttrModified', + self._syncA, + false + ); + this.$element[0].addEventListener( + 'DOMNodeInserted', + self._syncS, + false + ); + this.$element[0].addEventListener( + 'DOMNodeRemoved', + self._syncS, + false + ); + } + }; + + Select2.prototype._registerDataEvents = function () { + var self = this; + + this.dataAdapter.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerSelectionEvents = function () { + var self = this; + var nonRelayEvents = ['toggle', 'focus']; + + this.selection.on('toggle', function () { + self.toggleDropdown(); + }); + + this.selection.on('focus', function (params) { + self.focus(params); + }); + + this.selection.on('*', function (name, params) { + if ($.inArray(name, nonRelayEvents) !== -1) { + return; + } + + self.trigger(name, params); + }); + }; + + Select2.prototype._registerDropdownEvents = function () { + var self = this; + + this.dropdown.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerResultsEvents = function () { + var self = this; + + this.results.on('*', function (name, params) { + self.trigger(name, params); + }); + }; + + Select2.prototype._registerEvents = function () { + var self = this; + + this.on('open', function () { + self.$container.addClass('select2-container--open'); + }); + + this.on('close', function () { + self.$container.removeClass('select2-container--open'); + }); + + this.on('enable', function () { + self.$container.removeClass('select2-container--disabled'); + }); + + this.on('disable', function () { + self.$container.addClass('select2-container--disabled'); + }); + + this.on('blur', function () { + self.$container.removeClass('select2-container--focus'); + }); + + this.on('query', function (params) { + if (!self.isOpen()) { + self.trigger('open', {}); + } + + this.dataAdapter.query(params, function (data) { + self.trigger('results:all', { + data: data, + query: params + }); + }); + }); + + this.on('query:append', function (params) { + this.dataAdapter.query(params, function (data) { + self.trigger('results:append', { + data: data, + query: params + }); + }); + }); + + this.on('keypress', function (evt) { + var key = evt.which; + + if (self.isOpen()) { + if (key === KEYS.ESC || key === KEYS.TAB || + (key === KEYS.UP && evt.altKey)) { + self.close(); + + evt.preventDefault(); + } else if (key === KEYS.ENTER) { + self.trigger('results:select', {}); + + evt.preventDefault(); + } else if ((key === KEYS.SPACE && evt.ctrlKey)) { + self.trigger('results:toggle', {}); + + evt.preventDefault(); + } else if (key === KEYS.UP) { + self.trigger('results:previous', {}); + + evt.preventDefault(); + } else if (key === KEYS.DOWN) { + self.trigger('results:next', {}); + + evt.preventDefault(); + } + } else { + if (key === KEYS.ENTER || key === KEYS.SPACE || + (key === KEYS.DOWN && evt.altKey)) { + self.open(); + + evt.preventDefault(); + } + } + }); + }; + + Select2.prototype._syncAttributes = function () { + this.options.set('disabled', this.$element.prop('disabled')); + + if (this.options.get('disabled')) { + if (this.isOpen()) { + this.close(); + } + + this.trigger('disable', {}); + } else { + this.trigger('enable', {}); + } + }; + + Select2.prototype._syncSubtree = function (evt, mutations) { + var changed = false; + var self = this; + + // Ignore any mutation events raised for elements that aren't options or + // optgroups. This handles the case when the select element is destroyed + if ( + evt && evt.target && ( + evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP' + ) + ) { + return; + } + + if (!mutations) { + // If mutation events aren't supported, then we can only assume that the + // change affected the selections + changed = true; + } else if (mutations.addedNodes && mutations.addedNodes.length > 0) { + for (var n = 0; n < mutations.addedNodes.length; n++) { + var node = mutations.addedNodes[n]; + + if (node.selected) { + changed = true; + } + } + } else if (mutations.removedNodes && mutations.removedNodes.length > 0) { + changed = true; + } + + // Only re-pull the data if we think there is a change + if (changed) { + this.dataAdapter.current(function (currentData) { + self.trigger('selection:update', { + data: currentData + }); + }); + } + }; + + /** + * Override the trigger method to automatically trigger pre-events when + * there are events that can be prevented. + */ + Select2.prototype.trigger = function (name, args) { + var actualTrigger = Select2.__super__.trigger; + var preTriggerMap = { + 'open': 'opening', + 'close': 'closing', + 'select': 'selecting', + 'unselect': 'unselecting' + }; + + if (args === undefined) { + args = {}; + } + + if (name in preTriggerMap) { + var preTriggerName = preTriggerMap[name]; + var preTriggerArgs = { + prevented: false, + name: name, + args: args + }; + + actualTrigger.call(this, preTriggerName, preTriggerArgs); + + if (preTriggerArgs.prevented) { + args.prevented = true; + + return; + } + } + + actualTrigger.call(this, name, args); + }; + + Select2.prototype.toggleDropdown = function () { + if (this.options.get('disabled')) { + return; + } + + if (this.isOpen()) { + this.close(); + } else { + this.open(); + } + }; + + Select2.prototype.open = function () { + if (this.isOpen()) { + return; + } + + this.trigger('query', {}); + }; + + Select2.prototype.close = function () { + if (!this.isOpen()) { + return; + } + + this.trigger('close', {}); + }; + + Select2.prototype.isOpen = function () { + return this.$container.hasClass('select2-container--open'); + }; + + Select2.prototype.hasFocus = function () { + return this.$container.hasClass('select2-container--focus'); + }; + + Select2.prototype.focus = function (data) { + // No need to re-trigger focus events if we are already focused + if (this.hasFocus()) { + return; + } + + this.$container.addClass('select2-container--focus'); + this.trigger('focus', {}); + }; + + Select2.prototype.enable = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("enable")` method has been deprecated and will' + + ' be removed in later Select2 versions. Use $element.prop("disabled")' + + ' instead.' + ); + } + + if (args == null || args.length === 0) { + args = [true]; + } + + var disabled = !args[0]; + + this.$element.prop('disabled', disabled); + }; + + Select2.prototype.data = function () { + if (this.options.get('debug') && + arguments.length > 0 && window.console && console.warn) { + console.warn( + 'Select2: Data can no longer be set using `select2("data")`. You ' + + 'should consider setting the value instead using `$element.val()`.' + ); + } + + var data = []; + + this.dataAdapter.current(function (currentData) { + data = currentData; + }); + + return data; + }; + + Select2.prototype.val = function (args) { + if (this.options.get('debug') && window.console && console.warn) { + console.warn( + 'Select2: The `select2("val")` method has been deprecated and will be' + + ' removed in later Select2 versions. Use $element.val() instead.' + ); + } + + if (args == null || args.length === 0) { + return this.$element.val(); + } + + var newVal = args[0]; + + if ($.isArray(newVal)) { + newVal = $.map(newVal, function (obj) { + return obj.toString(); + }); + } + + this.$element.val(newVal).trigger('change'); + }; + + Select2.prototype.destroy = function () { + this.$container.remove(); + + if (this.$element[0].detachEvent) { + this.$element[0].detachEvent('onpropertychange', this._syncA); + } + + if (this._observer != null) { + this._observer.disconnect(); + this._observer = null; + } else if (this.$element[0].removeEventListener) { + this.$element[0] + .removeEventListener('DOMAttrModified', this._syncA, false); + this.$element[0] + .removeEventListener('DOMNodeInserted', this._syncS, false); + this.$element[0] + .removeEventListener('DOMNodeRemoved', this._syncS, false); + } + + this._syncA = null; + this._syncS = null; + + this.$element.off('.select2'); + this.$element.attr('tabindex', this.$element.data('old-tabindex')); + + this.$element.removeClass('select2-hidden-accessible'); + this.$element.attr('aria-hidden', 'false'); + this.$element.removeData('select2'); + + this.dataAdapter.destroy(); + this.selection.destroy(); + this.dropdown.destroy(); + this.results.destroy(); + + this.dataAdapter = null; + this.selection = null; + this.dropdown = null; + this.results = null; + }; + + Select2.prototype.render = function () { + var $container = $( + '' + + '' + + '' + + '' + ); + + $container.attr('dir', this.options.get('dir')); + + this.$container = $container; + + this.$container.addClass('select2-container--' + this.options.get('theme')); + + $container.data('element', this.$element); + + return $container; + }; + + return Select2; +}); + +S2.define('jquery-mousewheel',[ + 'jquery' +], function ($) { + // Used to shim jQuery.mousewheel for non-full builds. + return $; +}); + +S2.define('jquery.select2',[ + 'jquery', + 'jquery-mousewheel', + + './select2/core', + './select2/defaults' +], function ($, _, Select2, Defaults) { + if ($.fn.select2 == null) { + // All methods that should return the element + var thisMethods = ['open', 'close', 'destroy']; + + $.fn.select2 = function (options) { + options = options || {}; + + if (typeof options === 'object') { + this.each(function () { + var instanceOptions = $.extend(true, {}, options); + + var instance = new Select2($(this), instanceOptions); + }); + + return this; + } else if (typeof options === 'string') { + var ret; + var args = Array.prototype.slice.call(arguments, 1); + + this.each(function () { + var instance = $(this).data('select2'); + + if (instance == null && window.console && console.error) { + console.error( + 'The select2(\'' + options + '\') method was called on an ' + + 'element that is not using Select2.' + ); + } + + ret = instance[options].apply(instance, args); + }); + + // Check if we should be returning `this` + if ($.inArray(options, thisMethods) > -1) { + return this; + } + + return ret; + } else { + throw new Error('Invalid arguments for Select2: ' + options); + } + }; + } + + if ($.fn.select2.defaults == null) { + $.fn.select2.defaults = Defaults; + } + + return Select2; +}); + + // Return the AMD loader configuration so it can be used outside of this file + return { + define: S2.define, + require: S2.require + }; +}()); + + // Autoload the jQuery bindings + // We know that all of the modules exist above this, so we're safe + var select2 = S2.require('jquery.select2'); + + // Hold the AMD module references on the jQuery function that was just loaded + // This allows Select2 to use the internal loader outside of this file, such + // as in the language files. + jQuery.fn.select2.amd = S2; + + // Return the Select2 instance for anyone who is importing it. + return select2; +})); diff --git a/asset/static/libs/select2-4.0.3/js/select2.min.js b/asset/static/libs/select2-4.0.3/js/select2.min.js new file mode 100644 index 0000000..43f0a65 --- /dev/null +++ b/asset/static/libs/select2-4.0.3/js/select2.min.js @@ -0,0 +1,3 @@ +/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.slice(0,n.length-1).concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=v.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),n.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var c=r[a];delete r[a],t[a]=!0,m.apply(b,c)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||a,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;n0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;hc;c++)a[c].apply(this,b)},c.Observable=d,c.generateChars=function(a){for(var b="",c=0;a>c;c++){var d=Math.floor(36*Math.random());b+=d.toString(36)}return b},c.bind=function(a,b){return function(){a.apply(b,arguments)}},c._convertData=function(a){for(var b in a){var c=b.split("-"),d=a;if(1!==c.length){for(var e=0;e":">",'"':""","'":"'","/":"/"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('
          ');return this.options.get("multiple")&&b.attr("aria-multiselectable","true"),this.$results=b,b},c.prototype.clear=function(){this.$results.empty()},c.prototype.displayMessage=function(b){var c=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var d=a('
        • '),e=this.options.get("translations").get(b.message);d.append(c(e(b.args))),d[0].className+=" select2-results__message",this.$results.append(d)},c.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},c.prototype.append=function(a){this.hideLoading();var b=[];if(null==a.results||0===a.results.length)return void(0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"}));a.results=this.sort(a.results);for(var c=0;c0?b.first().trigger("mouseenter"):a.first().trigger("mouseenter"),this.ensureHighlightVisible()},c.prototype.setClasses=function(){var b=this;this.data.current(function(c){var d=a.map(c,function(a){return a.id.toString()}),e=b.$results.find(".select2-results__option[aria-selected]");e.each(function(){var b=a(this),c=a.data(this,"data"),e=""+c.id;null!=c.element&&c.element.selected||null==c.element&&a.inArray(e,d)>-1?b.attr("aria-selected","true"):b.attr("aria-selected","false")})})},c.prototype.showLoading=function(a){this.hideLoading();var b=this.options.get("translations").get("searching"),c={disabled:!0,loading:!0,text:b(a)},d=this.option(c);d.className+=" loading-results",this.$results.prepend(d)},c.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},c.prototype.option=function(b){var c=document.createElement("li");c.className="select2-results__option";var d={role:"treeitem","aria-selected":"false"};b.disabled&&(delete d["aria-selected"],d["aria-disabled"]="true"),null==b.id&&delete d["aria-selected"],null!=b._resultId&&(c.id=b._resultId),b.title&&(c.title=b.title),b.children&&(d.role="group",d["aria-label"]=b.text,delete d["aria-selected"]);for(var e in d){var f=d[e];c.setAttribute(e,f)}if(b.children){var g=a(c),h=document.createElement("strong");h.className="select2-results__group";a(h);this.template(b,h);for(var i=[],j=0;j",{"class":"select2-results__options select2-results__options--nested"});m.append(i),g.append(h),g.append(m)}else this.template(b,c);return a.data(c,"data",b),c},c.prototype.bind=function(b,c){var d=this,e=b.id+"-results";this.$results.attr("id",e),b.on("results:all",function(a){d.clear(),d.append(a.data),b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("results:append",function(a){d.append(a.data),b.isOpen()&&d.setClasses()}),b.on("query",function(a){d.hideMessages(),d.showLoading(a)}),b.on("select",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("unselect",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("open",function(){d.$results.attr("aria-expanded","true"),d.$results.attr("aria-hidden","false"),d.setClasses(),d.ensureHighlightVisible()}),b.on("close",function(){d.$results.attr("aria-expanded","false"),d.$results.attr("aria-hidden","true"),d.$results.removeAttr("aria-activedescendant")}),b.on("results:toggle",function(){var a=d.getHighlightedResults();0!==a.length&&a.trigger("mouseup")}),b.on("results:select",function(){var a=d.getHighlightedResults();if(0!==a.length){var b=a.data("data");"true"==a.attr("aria-selected")?d.trigger("close",{}):d.trigger("select",{data:b})}}),b.on("results:previous",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a);if(0!==c){var e=c-1;0===a.length&&(e=0);var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top,h=f.offset().top,i=d.$results.scrollTop()+(h-g);0===e?d.$results.scrollTop(0):0>h-g&&d.$results.scrollTop(i)}}),b.on("results:next",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a),e=c+1;if(!(e>=b.length)){var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top+d.$results.outerHeight(!1),h=f.offset().top+f.outerHeight(!1),i=d.$results.scrollTop()+h-g;0===e?d.$results.scrollTop(0):h>g&&d.$results.scrollTop(i)}}),b.on("results:focus",function(a){a.element.addClass("select2-results__option--highlighted")}),b.on("results:message",function(a){d.displayMessage(a)}),a.fn.mousewheel&&this.$results.on("mousewheel",function(a){var b=d.$results.scrollTop(),c=d.$results.get(0).scrollHeight-b+a.deltaY,e=a.deltaY>0&&b-a.deltaY<=0,f=a.deltaY<0&&c<=d.$results.height();e?(d.$results.scrollTop(0),a.preventDefault(),a.stopPropagation()):f&&(d.$results.scrollTop(d.$results.get(0).scrollHeight-d.$results.height()),a.preventDefault(),a.stopPropagation())}),this.$results.on("mouseup",".select2-results__option[aria-selected]",function(b){var c=a(this),e=c.data("data");return"true"===c.attr("aria-selected")?void(d.options.get("multiple")?d.trigger("unselect",{originalEvent:b,data:e}):d.trigger("close",{})):void d.trigger("select",{originalEvent:b,data:e})}),this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(b){var c=a(this).data("data");d.getHighlightedResults().removeClass("select2-results__option--highlighted"),d.trigger("results:focus",{data:c,element:a(this)})})},c.prototype.getHighlightedResults=function(){var a=this.$results.find(".select2-results__option--highlighted");return a},c.prototype.destroy=function(){this.$results.remove()},c.prototype.ensureHighlightVisible=function(){var a=this.getHighlightedResults();if(0!==a.length){var b=this.$results.find("[aria-selected]"),c=b.index(a),d=this.$results.offset().top,e=a.offset().top,f=this.$results.scrollTop()+(e-d),g=e-d;f-=2*a.outerHeight(!1),2>=c?this.$results.scrollTop(0):(g>this.$results.outerHeight()||0>g)&&this.$results.scrollTop(f)}},c.prototype.template=function(b,c){var d=this.options.get("templateResult"),e=this.options.get("escapeMarkup"),f=d(b,c);null==f?c.style.display="none":"string"==typeof f?c.innerHTML=e(f):a(c).append(f)},c}),b.define("select2/keys",[],function(){var a={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return a}),b.define("select2/selection/base",["jquery","../utils","../keys"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,b.Observable),d.prototype.render=function(){var b=a('');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),b.attr("title",this.$element.attr("title")),b.attr("tabindex",this._tabindex),this.$selection=b,b},d.prototype.bind=function(a,b){var d=this,e=(a.id+"-container",a.id+"-results");this.container=a,this.$selection.on("focus",function(a){d.trigger("focus",a)}),this.$selection.on("blur",function(a){d._handleBlur(a)}),this.$selection.on("keydown",function(a){d.trigger("keypress",a),a.which===c.SPACE&&a.preventDefault()}),a.on("results:focus",function(a){d.$selection.attr("aria-activedescendant",a.data._resultId)}),a.on("selection:update",function(a){d.update(a.data)}),a.on("open",function(){d.$selection.attr("aria-expanded","true"),d.$selection.attr("aria-owns",e),d._attachCloseHandler(a)}),a.on("close",function(){d.$selection.attr("aria-expanded","false"),d.$selection.removeAttr("aria-activedescendant"),d.$selection.removeAttr("aria-owns"),d.$selection.focus(),d._detachCloseHandler(a)}),a.on("enable",function(){d.$selection.attr("tabindex",d._tabindex)}),a.on("disable",function(){d.$selection.attr("tabindex","-1")})},d.prototype._handleBlur=function(b){var c=this;window.setTimeout(function(){document.activeElement==c.$selection[0]||a.contains(c.$selection[0],document.activeElement)||c.trigger("blur",b)},1)},d.prototype._attachCloseHandler=function(b){a(document.body).on("mousedown.select2."+b.id,function(b){var c=a(b.target),d=c.closest(".select2"),e=a(".select2.select2-container--open");e.each(function(){var b=a(this);if(this!=d[0]){var c=b.data("element");c.select2("close")}})})},d.prototype._detachCloseHandler=function(b){a(document.body).off("mousedown.select2."+b.id)},d.prototype.position=function(a,b){var c=b.find(".selection");c.append(a)},d.prototype.destroy=function(){this._detachCloseHandler(this.container)},d.prototype.update=function(a){throw new Error("The `update` method must be defined in child classes.")},d}),b.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(a,b,c,d){function e(){e.__super__.constructor.apply(this,arguments)}return c.Extend(e,b),e.prototype.render=function(){var a=e.__super__.render.call(this);return a.addClass("select2-selection--single"),a.html(''),a},e.prototype.bind=function(a,b){var c=this;e.__super__.bind.apply(this,arguments);var d=a.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",d),this.$selection.attr("aria-labelledby",d),this.$selection.on("mousedown",function(a){1===a.which&&c.trigger("toggle",{originalEvent:a})}),this.$selection.on("focus",function(a){}),this.$selection.on("blur",function(a){}),a.on("focus",function(b){a.isOpen()||c.$selection.focus()}),a.on("selection:update",function(a){c.update(a.data)})},e.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},e.prototype.display=function(a,b){var c=this.options.get("templateSelection"),d=this.options.get("escapeMarkup");return d(c(a,b))},e.prototype.selectionContainer=function(){return a("")},e.prototype.update=function(a){if(0===a.length)return void this.clear();var b=a[0],c=this.$selection.find(".select2-selection__rendered"),d=this.display(b,c);c.empty().append(d),c.prop("title",b.title||b.text)},e}),b.define("select2/selection/multiple",["jquery","./base","../utils"],function(a,b,c){function d(a,b){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--multiple"),a.html('
            '),a},d.prototype.bind=function(b,c){var e=this;d.__super__.bind.apply(this,arguments),this.$selection.on("click",function(a){e.trigger("toggle",{originalEvent:a})}),this.$selection.on("click",".select2-selection__choice__remove",function(b){if(!e.options.get("disabled")){var c=a(this),d=c.parent(),f=d.data("data");e.trigger("unselect",{originalEvent:b,data:f})}})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a,b){var c=this.options.get("templateSelection"),d=this.options.get("escapeMarkup");return d(c(a,b))},d.prototype.selectionContainer=function(){var b=a('
          • ×
          • ');return b},d.prototype.update=function(a){if(this.clear(),0!==a.length){for(var b=[],d=0;d1;if(d||c)return a.call(this,b);this.clear();var e=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(e)},b}),b.define("select2/selection/allowClear",["jquery","../keys"],function(a,b){function c(){}return c.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(a){d._handleClear(a)}),b.on("keypress",function(a){d._handleKeyboardClear(a,b)})},c.prototype._handleClear=function(a,b){if(!this.options.get("disabled")){var c=this.$selection.find(".select2-selection__clear");if(0!==c.length){b.stopPropagation();for(var d=c.data("data"),e=0;e0||0===c.length)){var d=a('×');d.data("data",c),this.$selection.find(".select2-selection__rendered").prepend(d)}},c}),b.define("select2/selection/search",["jquery","../utils","../keys"],function(a,b,c){function d(a,b,c){a.call(this,b,c)}return d.prototype.render=function(b){var c=a('');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return this._transferTabIndex(),d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.trigger("focus")}),b.on("close",function(){e.$search.val(""),e.$search.removeAttr("aria-activedescendant"),e.$search.trigger("focus")}),b.on("enable",function(){e.$search.prop("disabled",!1),e._transferTabIndex()}),b.on("disable",function(){e.$search.prop("disabled",!0)}),b.on("focus",function(a){e.$search.trigger("focus")}),b.on("results:focus",function(a){e.$search.attr("aria-activedescendant",a.id)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e._handleBlur(a)}),this.$selection.on("keydown",".select2-search--inline",function(a){a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented();var b=a.which;if(b===c.BACKSPACE&&""===e.$search.val()){var d=e.$searchContainer.prev(".select2-selection__choice");if(d.length>0){var f=d.data("data");e.searchRemoveChoice(f),a.preventDefault()}}});var f=document.documentMode,g=f&&11>=f;this.$selection.on("input.searchcheck",".select2-search--inline",function(a){return g?void e.$selection.off("input.search input.searchcheck"):void e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(a){if(g&&"input"===a.type)return void e.$selection.off("input.search input.searchcheck");var b=a.which;b!=c.SHIFT&&b!=c.CTRL&&b!=c.ALT&&b!=c.TAB&&e.handleSearch(a)})},d.prototype._transferTabIndex=function(a){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){var c=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch(),c&&this.$search.focus()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.$search.val(b.text),this.handleSearch()},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{var b=this.$search.val().length+1;a=.75*b+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){var a={"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ω":"ω","ς":"σ"};return a}),b.define("select2/data/base",["../utils"],function(a){function b(a,c){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(a){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(a,b){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(a,b){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),d+=null!=c.id?"-"+c.id.toString():"-"+a.generateChars(4)},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change"); +if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){d.status&&"0"===d.status||e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&null!=a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.call(this,c,d),a.isArray(e))for(var h=0;h0&&b.term.length>this.maximumInputLength?void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;return d.maximumSelectionLength>0&&f>=d.maximumSelectionLength?void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}}):void a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.bind=function(){},c.prototype.position=function(a,b){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a,b){function c(){}return c.prototype.render=function(b){var c=b.call(this),d=a('');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},c.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(b){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("focus",function(){c.isOpen()&&e.$search.focus()}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){var b=e.showSearch(a);b?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},c.prototype.handleSearch=function(a){if(!this._keyUpPrevented){var b=this.$search.val();this.trigger("query",{term:b})}this._keyUpPrevented=!1},c.prototype.showSearch=function(a,b){return!0},c}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){var c=e.$results.offset().top+e.$results.outerHeight(!1),d=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1);c+50>=d&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('
          • '),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(b,c,d){this.$dropdownParent=d.get("dropdownParent")||a(document.body),b.call(this,c,d)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.destroy=function(a){a.call(this),this.$dropdownContainer.remove()},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a(""),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(a){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c,d){var e=this,f="scroll.select2."+d.id,g="resize.select2."+d.id,h="orientationchange.select2."+d.id,i=this.$container.parents().filter(b.hasScroll);i.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),i.on(f,function(b){var c=a(this).data("select2-scroll-position");a(this).scrollTop(c.y)}),a(window).on(f+" "+g+" "+h,function(a){e._positionDropdown(),e._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c,d){var e="scroll.select2."+d.id,f="resize.select2."+d.id,g="orientationchange.select2."+d.id,h=this.$container.parents().filter(b.hasScroll);h.off(e),a(window).off(e+" "+f+" "+g)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=this.$container.offset();f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.topf.bottom+h.height,l={left:f.left,top:g.bottom},m=this.$dropdownParent;"static"===m.css("position")&&(m=m.offsetParent());var n=m.offset();l.top-=n.top,l.left-=n.left,c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-n.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.position="relative",a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(a){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),(null!=l.tokenSeparators||null!=l.tokenizer)&&(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.multiple?l.selectionAdapter=e:l.selectionAdapter=d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){var h=e.children[g],i=c(d,h);null==i&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var j=b(e.text).toUpperCase(),k=b(d.term).toUpperCase();return j.indexOf(k)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)};var E=new D;return E}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(a.prop("dir")?this.options.dir=a.prop("dir"):a.closest("[dir]").prop("dir")?this.options.dir=a.closest("[dir]").prop("dir"):this.options.dir="ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b=b.replace(/(:|\.|\[|\]|,)/g,""),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return 0>=e?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;i>h;h+=1){var j=g[h].replace(/\s/g,""),k=j.match(c);if(null!==k&&k.length>=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this.$element.on("focus.select2",function(a){b.trigger("focus",a)}),this._syncA=c.bind(this._syncAttributes,this),this._syncS=c.bind(this._syncSubtree,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._syncA);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._syncA),a.each(c,b._syncS)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})):this.$element[0].addEventListener&&(this.$element[0].addEventListener("DOMAttrModified",b._syncA,!1),this.$element[0].addEventListener("DOMNodeInserted",b._syncS,!1),this.$element[0].addEventListener("DOMNodeRemoved",b._syncS,!1))},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle","focus"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("focus",function(a){b.focus(a)}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open",{}),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ESC||c===d.TAB||c===d.UP&&b.altKey?(a.close(),b.preventDefault()):c===d.ENTER?(a.trigger("results:select",{}),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle",{}),b.preventDefault()):c===d.UP?(a.trigger("results:previous",{}),b.preventDefault()):c===d.DOWN&&(a.trigger("results:next",{}),b.preventDefault()):(c===d.ENTER||c===d.SPACE||c===d.DOWN&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},e.prototype._syncSubtree=function(a,b){var c=!1,d=this;if(!a||!a.target||"OPTION"===a.target.nodeName||"OPTGROUP"===a.target.nodeName){if(b)if(b.addedNodes&&b.addedNodes.length>0)for(var e=0;e0&&(c=!0);else c=!0;c&&this.dataAdapter.current(function(a){d.trigger("selection:update",{data:a})})}},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(void 0===b&&(b={}),a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||this.trigger("query",{})},e.prototype.close=function(){this.isOpen()&&this.trigger("close",{})},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")},e.prototype.focus=function(a){this.hasFocus()||(this.$container.addClass("select2-container--focus"),this.trigger("focus",{}))},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),(null==a||0===a.length)&&(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._syncA),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&(this.$element[0].removeEventListener("DOMAttrModified",this._syncA,!1),this.$element[0].removeEventListener("DOMNodeInserted",this._syncS,!1),this.$element[0].removeEventListener("DOMNodeRemoved",this._syncS,!1)),this._syncA=null,this._syncS=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null; +},e.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery-mousewheel",["jquery"],function(a){return a}),b.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(a,b,c,d){if(null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if(b=b||{},"object"==typeof b)return this.each(function(){var d=a.extend(!0,{},b);new c(a(this),d)}),this;if("string"==typeof b){var d,f=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=a(this).data("select2");null==c&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2."),d=c[b].apply(c,f)}),a.inArray(b,e)>-1?this:d}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c}); \ No newline at end of file diff --git a/asset/static/stylesheets/common/custom.css b/asset/static/stylesheets/common/custom.css new file mode 100755 index 0000000..5a1446d --- /dev/null +++ b/asset/static/stylesheets/common/custom.css @@ -0,0 +1,217 @@ +/* Write your custom CSS here */ + +/*no pad style*/ +.no-padding { + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + border: 0px; + -webkit-box-shadow: 0; + box-shadow: 0; +} + +/* status related color row */ +table .basket_status_price_ready { + color: #eb3c6a; +} + +table .basket_status_priced { + color: #2bab2b; +} + +table .basket_status_delivered { + color: #2bab2b; +} + +table .basket_status_canceled { + color: #ababab; +} + +table .basket_status_refund_after_adjust { + color: #ababab; +} + +table .basket_status_refund_before_adjust { + color: #ababab; +} + +table .upload_status_initial { + color: #eb3c6a; +} + +table .upload_status_handled { + color: #2bab2b; +} + +table .upload_status_discarded { + color: #ababab; +} + +/* label related style */ + +.basket-item-grid table .net_price { + white-space: nowrap; + background-color: #eb3c6a; + color: #fff; +} + +.basket-item-grid table .rest_area { + text-align: right; +} + +.basket-item-grid table .rest_area dl { + display: inline-block; + min-width: 100px; + padding-right: 15px; +} + +.basket-item-grid table dt { + text-align: center; +} + +.basket-item-grid table dd { + text-align: right; + font-size: 15pt; +} + +.basket-item-grid table .net_price a { + color: #fff; + text-decoration: none; +} + +.basket-confirm-bar-widget .btn-pricing, +.basket-confirm-bar-widget .btn-delivering { + background-color: #eb3c6a; + color: #fff; +} + +.upload-confirm-bar-widget .btn-handle { + background-color: #eb3c6a; + color: #fff; +} + +.header-status-progress .nav-item.active .nav-link { + color: #eb3c6a; + background: none; + font-weight: 600; +} + +.company-description .important-info * { + font-size: 27px; +} + +.positive * { + color: #2bab2b; +} + +.negative * { + color: #eb3c6a; +} + +.card-positive { + background: #2bab2b; +} + +.card-positive .card-header { + color: #fff; +} + +.card-positive .card-block { + color: #fff; +} + +.card-positive .card-header .card-control a { + color: #fff; +} + +.card-positive .card-header .card-control a:hover { + color: #f1f1f1; +} + +.tx-registration-bar .btn-registration { + background-color: #eb3c6a; + color: #fff; +} + +.image-cell .preview { + display: none; + position: absolute; + border: 1px solid #000; + width: 400px; + height: 400px; +} + +/*justified-gallery figure css definition*/ +.justified-gallery > figure { + position: absolute; + display: inline-block; + overflow: hidden; + /* background: #888888; To have gray placeholders while the gallery is loading with waitThumbnailsLoad = false */ + filter: "alpha(opacity=10)"; + opacity: 0.1; +} + +.justified-gallery > figure > img, +.justified-gallery > figure > a > img { + position: absolute; + top: 50%; + left: 50%; + margin: 0; + padding: 0; + border: none; + filter: "alpha(opacity=0)"; + opacity: 0; +} + +.justified-gallery > figure > .caption { + display: none; + position: absolute; + bottom: 0; + padding: 5px; + background-color: #000000; + left: 0; + right: 0; + margin: 0; + color: white; + font-size: 12px; + font-weight: 300; + font-family: sans-serif; +} + +.justified-gallery > figure > .caption.caption-visible { + display: initial; + filter: "alpha(opacity=70)"; + opacity: 0.7; + -webkit-transition: opacity 500ms ease-in; + -moz-transition: opacity 500ms ease-in; + -o-transition: opacity 500ms ease-in; + transition: opacity 500ms ease-in; +} + +/*justified-gallery figure css definition end */ + +/* PhotoSwipe preview load glitch */ +.pswp__img { + height: auto !important; +} + +.top-menu .navbar-nav .nav-item + .nav-item { + margin: 0; +} + +.top-menu.collapse.show { + background-color: #fff; +} +button.navbar-toggler{ + line-height: 60px; + padding: 0 15px 0 15px; + vertical-align: middle; + display: table-cell; + text-align: center; + position: absolute; + right: 0rem; +} +.dropdown-toggle::after { + content: none; +} diff --git a/asset/static/stylesheets/common/modern.css b/asset/static/stylesheets/common/modern.css new file mode 100755 index 0000000..fb2428d --- /dev/null +++ b/asset/static/stylesheets/common/modern.css @@ -0,0 +1,2402 @@ + +body { + position: relative; + height: 100%!important; + width: 100%; + font-family: 'Spoqa Han Sans',"Helvetica Neue",Helvetica,Arial,sans-serif!important; + font-size: 13px; + background: #ccc; + color: #4E5E6A; +} + +html { + height: 100%!important; + position: relative; +} + +*:hover, +*:active, +*:focus { + outline: none!important; +} + + +/* Typography */ + +p { + display: block; + font-size: 13px; + font-weight: normal; + letter-spacing: normal; + line-height: 22px; + margin: 0px 0px 10px 0px; + font-style: normal; + white-space: normal; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: 300; +} + +h1 { + font-size: 30px; +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 16px; +} + +h4 { + font-size: 14px; +} + +h5 { + font-size: 12px; +} + +h6 { + font-size: 10px; +} + +h3, +h4, +h5 { + font-weight: 600; +} + +.text-xs { + font-size: 10px; +} + +.text-sm { + font-size: 12px; +} + +.text-md { + font-size: 16px; +} + +.text-lg { + font-size: 32px; +} + +.text-xl { + font-size: 52px; +} + +.text-xxl { + font-size: 80px; +} + +.f-white { + color: #fff; +} + +.f-gray { + color: #ccc; +} + +.f-gray-dark { + color: #a2a2a2; +} + +.f-black { + color: #333; +} + +.f-green { + color: #22BAA0; +} + +.f-blue { + color: #127acb; +} + +.f-lblue { + color: #12AFCB; +} + +.f-purple { + color: #7a6fbe; +} + +.f-red { + color: #f25656; +} + +.f-yellow { + color: #f6d433; +} + +.f-orange { + color: #e79b2f; +} + +.text-default { + color: #ccc; +} + +.text-primary { + color: #7a6fbe; +} + +.text-success { + color: #22BAA0; +} + +.text-info { + color: #12AFCB; +} + +.text-warning { + color: #f6d433; +} + +.text-danger { + color: #f25656; +} + + +/* Icons */ + +.icon-xs { + font-size: 12px; +} + +.icon-sm { + font-size: 14px; +} + +.icon-md { + font-size: 16px; +} + +.icon-lg { + font-size: 18px; +} + +.icon-state-default { + color: #ccc; +} + +.icon-state-primary { + color: #7a6fbe; +} + +.icon-state-success { + color: #22BAA0; +} + +.icon-state-info { + color: #12AFCB; +} + +.icon-state-warning { + color: #f6d433; +} + +.icon-state-danger { + color: #f25656; +} + + + +/* Alert */ + +.alert { + border-radius: 0; + padding-top: 10px; + padding-bottom: 10px; + border: 0; +} + +.alert-success { + background: #e5f3df; +} + +.alert-info { + background: #d3e6f0; +} + +.alert-warning { + background: #f6f2dd; +} + +.alert-danger { + background: #f1d9d9; +} +/* titlebar style*/ + +.page-content { + background: #34425A; +} + +.navbar .logo-box { + background: #34425A; +} + +.navbar .logo-box a { + color: #fff; +} + +/* Custom Badges */ + +.badge { + -webkit-border-radius: 12px !important; + -moz-border-radius: 12px !important; + border-radius: 12px !important; + border-radius: 0px; + font-weight: 300; + font-size: 11px !important; + text-align: center; + vertical-align: middle; + line-height: 11px!important; + height: 18px; + padding: 3px 6px 3px 6px; + text-shadow: none !important; +} + +.badge.badge-roundless { + -webkit-border-radius: 0 !important; + -moz-border-radius: 0 !important; + border-radius: 0 !important; +} + +.badge.badge-default { + background: #f1f1f1; + color: #aaa; +} + +.badge.badge-primary { + background: #7a6fbe; + color: #FFF; +} + +.badge.badge-info { + background: #12AFCB; + color: #FFF; +} + +.badge.badge-success { + background: #22BAA0; + color: #FFF; +} + +.badge.badge-danger { + background: #f25656; + color: #FFF; +} + +.badge.badge-warning { + background: #f6d433; + color: #FFF; +} + +/* Backgrounds */ + +.bg-n { + background: transparent!important; +} + +.bg-primary { + background-color: #7a6fbe; + color: #fff; +} + +.bg-primary.dark { + background-color: #6e63b4; + color: #fff; +} + +.bg-primary.light { + background-color: #877cc7; + color: #fff; +} + +.bg-success { + background-color: #22BAA0; + color: #fff; +} + +.bg-success.dark { + background-color: #1da890; + color: #fff; +} + +.bg-success.light { + background-color: #32c6ad; + color: #fff; +} + +.bg-info { + background-color: #12AFCB; + color: #fff; +} + +.bg-info.dark { + background-color: #0ba0bb; + color: #fff; +} + +.bg-info.light { + background-color: #20beda; + color: #fff; +} + +.bg-warning { + background-color: #f6d433; + color: #fff; +} + +.bg-warning.dark { + background-color: #f1ca11; + color: #fff; +} + +.bg-warning.light { + background-color: #fada44; + color: #fff; +} + +.bg-danger { + background-color: #f25656; + color: #fff; +} + +.bg-danger.dark { + background-color: #e54f4f; + color: #fff; +} + +.bg-danger.light { + background-color: #f66d6d; + color: #fff; +} + +.bg-dark { + background-color: #333; + color: #fff; +} + +.bg-dark.dark { + background-color: #2b2b2b; + color: #fff; +} + +.bg-dark.light { + background-color: #3b3b3b; + color: #fff; +} + +.bg-light { + background-color: #f1f1f1; +} + +.bg-light.dark { + background-color: #e5e5e5; +} + +.bg-light.light { + background-color: #f9f9f9; +} + +.bg-gray { + background-color: #ccc; +} + +.bg-gray.dark { + background-color: #b9b9b9; +} + +.bg-gray.light { + background-color: #d7d7d7; +} + + +/* Buttons */ + +.btn { + font-size: 13px; + border: 1px solid transparent; + border-radius: 0; + outline: none!important; +} + +.btn-addon i { + position: relative; + float: left; + width: 35px; + height: 35px; + margin: -9px -17px; + margin-right: 16px; + line-height: 34px; + text-align: center; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; + background-color: rgba(0,0,0, 0.1); +} + +.btn-rounded.btn-addon i { + margin: -9px -20px; + margin-right: 14px; + border-radius: 50px; +} + +.btn-rounded.btn-addon.btn-sm i { + margin: -9px -20px; + margin-right: 14px; + border-radius: 50px; +} + +.btn-lg { + line-height: inherit; +} + +.btn-lg.btn-addon i { + width: 45px; + height: 45px; + margin: -11px -17px; + margin-right: 16px; + line-height: 45px; +} + +.btn-sm.btn-addon i { + width: 30px; + height: 30px; + margin: -6px -11px; + margin-right: 10px; + line-height: 30px; +} + +.btn-xs.btn-addon i { + width: 22px; + height: 22px; + margin: -2px -6px; + margin-right: 5px; + line-height: 22px; + font-size: 10px; +} + +.btn-rounded { + padding-left: 15px; + padding-right: 15px; + border-radius: 50px; +} + +.btn-group.open .dropdown-toggle { + box-shadow: none; +} + +.btn-default { + background-color: #fff; + color: #333; + border: 1px solid #e5e5e5; +} + +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #f1f1f1; + border-color: #e5e5e5; +} + +.btn-default:hover { + color: #333; + background-color: #f1f1f1; + border-color: #e5e5e5; +} + +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #f1f1f1; + border-color: #e5e5e5; +} + +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #f1f1f1; + border-color: #e5e5e5; +} + +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} + +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} + +.btn-default .badge { + color: #fff; + background-color: #333; +} + +.btn-primary { + color: #fff; + background-color: #7a6fbe; + border-color: transparent; +} + +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #6a5fac; + border-color: transparent; +} + +.btn-primary:hover { + color: #fff; + background-color: #6a5fac; + border-color: transparent; +} + +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #6a5fac; + border-color: transparent; +} + +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #6a5fac; + border-color: transparent; +} + +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} + +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #6a5fac; + border-color: transparent; +} + +.btn-primary .badge { + color: #6a5fac; + background-color: #fff; +} + +.btn-success { + color: #fff; + background-color: #22BAA0; + border-color: transparent; +} + +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #1DB198; + border-color: transparent; +} + +.btn-success:hover { + color: #fff; + background-color: #1DB198; + border-color: transparent; +} + +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #1DB198; + border-color: transparent; +} + +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #1DB198; + border-color: transparent; +} + +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} + +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #1DB198; + border-color: transparent; +} + +.btn-success .badge { + color: #1DB198; + background-color: #fff; +} + +.btn-info { + color: #fff; + background-color: #12AFCB; + border-color: transparent; +} + +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #08A7C3; + border-color: transparent; +} + +.btn-info:hover { + color: #fff; + background-color: #08A7C3; + border-color: transparent; +} + +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #08A7C3; + border-color: transparent; +} + +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #08A7C3; + border-color: transparent; +} + +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} + +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #08A7C3; + border-color: transparent; +} + +.btn-info .badge { + color: #12AFCB; + background-color: #fff; +} + +.btn-warning { + color: #fff; + background-color: #f2ca4c; + border-color: transparent; +} + +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #e8bf40; + border-color: transparent; +} + +.btn-warning:hover { + color: #fff; + background-color: #e8bf40; + border-color: transparent; +} + +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #e8bf40; + border-color: transparent; +} + +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #e8bf40; + border-color: transparent; +} + +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} + +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #e8bf40; + border-color: transparent; +} + +.btn-warning .badge { + color: #f2ca4c; + background-color: #fff; +} + +.btn-danger { + color: #fff; + background-color: #f25656; + border-color: transparent; +} + +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #e14444; + border-color: transparent; +} + +.btn-danger:hover { + color: #fff; + background-color: #e14444; + border-color: transparent; +} + +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #e14444; + border-color: transparent; +} + +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #e14444; + border-color: transparent; +} + +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} + +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #e14444; + border-color: transparent; +} + +.btn-danger .badge { + color: #f25656; + background-color: #fff; +} + +.btn-facebook { + background: #627AAC; + color: #fff; +} + +.btn-facebook:hover, +.btn-facebook:focus, +.btn-facebook:active { + background: #3B5998; + color: #fff; +} + +.btn-twitter { + background: #33BBF3; + color: #fff; +} + +.btn-twitter:hover, +.btn-twitter:focus, +.btn-twitter:active { + background: #00ABF0; + color: #fff; +} + +.btn-google { + background: #E0745B; + color: #fff; +} + +.btn-google:hover, +.btn-google:focus, +.btn-google:active { + background: #D95232; + color: #fff; +} + +.btn-youtube { + background: #D6464B; + color: #fff; +} + +.btn-youtube:hover, +.btn-youtube:focus, +.btn-youtube:active { + background: #CC181E; + color: #fff; +} + +.btn-vimeo { + background: #69C8FF; + color: #fff; +} + +.btn-vimeo:hover, +.btn-vimeo:focus, +.btn-vimeo:active { + background: #44BBFF; + color: #fff; +} + +.btn-dribbble { + background: #E094B7; + color: #fff; +} + +.btn-dribbble:hover, +.btn-dribbble:focus, +.btn-dribbble:active { + background: #D97AA5; + color: #fff; +} + +.btn-github { + background: #848484; + color: #fff; +} + +.btn-github:hover, +.btn-github:focus, +.btn-github:active { + background: #666666; + color: #fff; +} + +.btn-instagram { + background: #658EAF; + color: #fff; +} + +.btn-instagram:hover, +.btn-instagram:focus, +.btn-instagram:active { + background: #3F729B; + color: #fff; +} + +.btn-pinterest { + background: #BE464B; + color: #fff; +} + +.btn-pinterest:hover, +.btn-pinterest:focus, +.btn-pinterest:active { + background: #AE181F; + color: #fff; +} + +.btn-vk { + background: #7D9BBB; + color: #fff; +} + +.btn-vk:hover, +.btn-vk:focus, +.btn-vk:active { + background: #5D83AA; + color: #fff; +} + +.btn-rss { + background: #F19958; + color: #fff; +} + +.btn-rss:hover, +.btn-rss:focus, +.btn-rss:active { + background: #EE802F; + color: #fff; +} + +.btn-flickr { + background: #3395C4; + color: #fff; +} + +.btn-flickr:hover, +.btn-flickr:focus, +.btn-flickr:active { + background: #007BB6; + color: #fff; +} + +/* Panel */ + +.card { + -webkit-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + border: 0!important; + margin-bottom: 25px; + border-radius: 0; +} + +@media (min-width: 768px) { + .card > .row > div:first-child { + padding-left: 15px; + padding-right: 0; + } + + .card > .row > div:last-child { + padding-left: 0; + padding-right: 15px; + } +} + +.card .card-header { + padding: 20px 20px 20px 20px; + overflow: hidden; + border-top-left-radius: 0; + border-top-right-radius: 0; + border: 0!important; + height: 55px; + font-size: 14px; + font-weight: 600; +} + +.card .card-header .card-title { + font-size: 14px; + float: left; + margin: 0px; + padding: 0px; + font-weight: 600; +} + +.card .card-header .card-title small { + font-size: 80%; +} + +/*.panel .card-header .card-control {*/ + /*float: right;*/ + /*height: auto;*/ +/*}*/ + +/*.panel .card-header .card-control a {*/ + /*text-decoration: none;*/ + /*color: #ccc;*/ + /*margin-left: 5px;*/ + /*font-size: 14px;*/ + /*float: left;*/ +/*}*/ + +/*.panel .card-header .card-control a:hover {*/ + /*color: #a2a2a2;*/ +/*}*/ + +.card .card-block { + position: relative; + padding: 20px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.card .card-header + .card-block { + padding: 0 20px 20px 20px; +} + +.card-default .card-header { + background: #f1f1f1; + border-color: #e7e7e7; +} + +.card-default .card-header .card-control a { + color: #bbb; +} + +.card-default .card-header .card-control a:hover { + color: #a2a2a2; +} + +.card-primary .card-header { + background: #7a6fbe; + color: #fff; +} + +.card-primary .card-header .card-control a { + color: #fff; +} + +.card-primary .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-success .card-header { + background: #22BAA0; + color: #fff; +} + +.card-success .card-header .card-control a { + color: #fff; +} + +.card-success .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-info .card-header { + background: #12AFCB; + color: #fff; +} + +.card-info .card-header .card-control a { + color: #fff; +} + +.card-info .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-warning .card-header { + background: #f6d433; + color: #fff; +} + +.card-warning .card-header .card-control a { + color: #fff; +} + +.card-warning .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-danger .card-header { + background: #f25656; + color: #fff; +} + +.card-danger .card-header .card-control a { + color: #fff; +} + +.card-danger .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-transparent { + background: transparent; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.card-transparent .card-header .card-control a { + color: #ccc; +} + +.card-transparent .card-header .card-control a:hover { + color: #a2a2a2; +} + +.card-white { + background: #fff; +} + +.card-white .card-header .card-control a { + color: #ccc; +} + +.card-white .card-header .card-control a:hover { + color: #a2a2a2; +} + +.card-purple { + background: #7a6fbe; +} + +.card-purple .card-header { + color: #fff; +} + +.card-purple .card-block { + color: #fff; +} + +.card-purple .card-header .card-control a { + color: #fff; +} + +.card-purple .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-green { + background: #22BAA0; +} + +.card-green .card-header { + color: #fff; +} + +.card-green .card-block { + color: #fff; +} + +.card-green .card-header .card-control a { + color: #fff; +} + +.card-green .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-blue { + background: #12AFCB; +} + +.card-blue .card-header { + color: #fff; +} + +.card-blue .card-block { + color: #fff; +} + +.card-blue .card-header .card-control a { + color: #fff; +} + +.card-blue .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-yellow { + background: #f6d433; +} + +.card-yellow .card-header { + color: #fff; +} + +.card-yellow .card-block { + color: #fff; +} + +.card-yellow .card-header .card-control a { + color: #fff; +} + +.card-yellow .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-red { + background: #f25656; +} + +.card-red .card-header { + color: #fff; +} + +.card-red .card-block { + color: #fff; +} + +.card-red .card-header .card-control a { + color: #fff; +} + +.card-red .card-header .card-control a:hover { + color: #f1f1f1; +} + +.card-placeholder { + border: 2px dashed #ddd; + margin-bottom: 20px; +} + +/* Wells */ + +.well { + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + background-color: #F6F6F6; + border: 0; +} + + +/* Modals */ + +.modal { + z-index: 9999; +} + +.modal-content { + -webkit-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + border: 0; + border-radius: 0; +} + +.modal-header { + padding: 20px 20px 20px 20px; + overflow: hidden; + border-top-left-radius: 0; + border-top-right-radius: 0; + border: 0!important; + height: 55px; + font-size: 14px; + font-weight: 600; +} + +.modal-body { + position: relative; + padding: 20px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.modal-footer { + position: relative; + padding: 20px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: 0; +} + +.modal-header + .modal-body { + padding: 0 20px 20px 20px; +} + +.modal-body + .modal-footer { + padding: 0 20px 20px 20px; +} + +.modal-open { + overflow-y: auto!important; +} + +.modal-open { + padding: 0!important; +} + +.modal-backdrop { + z-index: 999; +} + +/* Pagination */ + +.pagination .page-item .page-link { + color: #5B5B5B; +} + +.pagination .active .page-link, +.pagination .active .page-link:hover, +.pagination .active .page-link:focus{ + background: #22BAA0; + border-color: #22BAA0; +} + + +/* Progress Bars */ + +.progress { + border-radius: 2px; +} + +.progress-squared { + border-radius: 0; +} + +.progress-xs { + height: 5px; +} + +.progress-sm { + height: 10px; +} + +.progress-md { + height: 15px; +} + +.progress-lg { + height: 25px; +} + +.progress-bar { + background-color: #7a6fbe; +} + +.progress-bar-success { + background-color: #22BAA0; +} + +.progress-bar-info { + background-color: #12AFCB; +} + +.progress-bar-warning { + background-color: #f6d433; +} + +.progress-bar-danger { + background-color: #f25656; +} + +/* Tabs */ + +.tab-content { + padding: 15px; + background: #fff; + +} +.nav-tabs > .nav-item > .nav-link { + border-radius: 0!important; + color: #777; + border-bottom: 1px solid #DDDDDD; +} + +.nav-tabs > .nav-item > .nav-link:hover { + background: #f1f1f1; +} +.nav-tabs > .nav-item.active > .nav-link, +.nav-tabs > .nav-item.active > .nav-link:hover, +.nav-tabs > .nav-item.active > .nav-link:focus { + color: #555; + cursor: default; + background-color: #fff; + border-bottom-color: #fff; +} + +.nav-pills > .nav-item > .nav-link { + color: #777; + border-radius: 0!important; +} + +.nav-pills > .nav-item.active > .nav-link, +.nav-pills > .nav-item.active > .nav-link:hover, +.nav-pills > .nav-item.active > .nav-link:focus { + color: #fff; + background-color: #7a6fbe; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > .nav-item { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > .nav-item > .nav-link { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.tabs-below > .nav-tabs > .nav-item > .nav-link:hover, +.tabs-below > .nav-tabs > .nav-item > .nav-link:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > .nav-link, +.tabs-below > .nav-tabs > .active > .nav-link:hover, +.tabs-below > .nav-tabs > .active > .nav-link:focus { + border-color: #fff #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > .nav-item, +.tabs-right > .nav-tabs > .nav-item { + + float: none; +} + +.tabs-left > .nav-tabs > .nav-item > .nav-link, +.tabs-right > .nav-tabs > .nav-item > .nav-link { + + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; + border-bottom: 0; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > .nav-item > .nav-link { + margin-right: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.tabs-left > .nav-tabs > .nav-item > .nav-link:hover, +.tabs-left > .nav-tabs > .nav-item > .nav-link:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > .nav-link, +.tabs-left > .nav-tabs .active > .nav-link:hover, +.tabs-left > .nav-tabs .active > .nav-link:focus { + border-color: #ddd transparent #ddd #ddd; + border-right-color: #ffffff; + border-bottom: 1px solid #DDDDDD; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > .nav-item > .nav-link { + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.tabs-right > .nav-tabs > .nav-item > .nav-link:hover, +.tabs-right > .nav-tabs > .nav-item > .nav-link:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > .nav-link, +.tabs-right > .nav-tabs .active > .nav-link:hover, +.tabs-right > .nav-tabs .active > .nav-link:focus { + + border-color: #ddd #ddd #ddd transparent; + border-left-color: #ffffff; + border-bottom: 1px solid #DDDDDD; +} + + + +/* Labels */ + +.label.label-default { + background: #fff; + border: 1px solid #e5e5e5; +} + +.label.label-success { + background: #22BAA0; +} + +.label.label-primary { + background: #7a6fbe; +} + +.label.label-info { + background: #12AFCB; +} + +.label.label-danger { + background: #f25656; +} + +.label.label-warning { + background: #f6d433; +} + + +/* Forms */ + +label { + font-size: 13px; + font-weight: normal; +} + +.controls label { + display: block; +} + +.form-control { + background: #fff; + border-radius: 0; + border: 1px solid #dce1e4; + box-shadow: none!important; + font-size: 13px; + padding: 6px 10px!important; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +input[disabled] { + background: #f7f7f7; + border-color: #d2d7db; +} + +.form-control:focus { + border: 1px solid #bdc5c9; + background: #fff; +} + +.help-block { + margin-bottom: 5px; +} + +.form-group.has-success .form-control, +.form-group.has-warning .form-control, +.form-group.has-error .form-control { + box-shadow: none; +} + +.form-group.has-success .form-control:focus { + border: 1px solid #22BAA0; + background: #fff; +} + +.form-group.has-warning .form-control:focus { + border: 1px solid #f6d433; + background: #fff; +} + +.form-group.has-error .form-control:focus { + border: 1px solid #f25656; + background: #fff; +} + +.form-group.has-success label { + color: #22BAA0; +} + +.form-group.has-warning label { + color: #f6d433; +} + +.form-group.has-error label { + color: #f25656; +} + +label.error { + color: #a94442; + font-weight: bold; + margin-top: 5px; + float: left; + font-size: 12px; +} + +input.form-control.input-rounded { + border-radius: 30px; +} + +.input-group .btn { + padding: 7px 12px; +} + +ol.linenums { + margin: 0; +} + +.select2-selection { + background: #fff!important; + border-radius: 0!important; + border: 1px solid #dce1e4!important; + box-shadow: none!important; + font-size: 13px!important; + padding: 6px 10px!important; + height: 34px!important; + -webkit-transition: all 0.2s ease-in-out!important; + -moz-transition: all 0.2s ease-in-out!important; + -o-transition: all 0.2s ease-in-out!important; + transition: all 0.2s ease-in-out!important; +} + +.select2-dropdown { + background: #fff; + border-radius: 0; + border: 1px solid #dce1e4; + border-top: 0; + box-shadow: none!important; + font-size: 13px; + padding: 6px 10px!important; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + z-index: 9999; +} + +.select2-dropdown.select2-dropdown--above { + border: 1px solid #dce1e4; + border-bottom: 0; +} + +.select2-selection--multiple .select2-selection__choice { + background: #f1f1f1!important; + border-radius: 0!important; + border: 1px solid #ccc!important; +} + +.select2-container--default .select2-selection--single .select2-selection__rendered, +.select2-container--default .select2-selection--multiple .select2-selection__rendered { + line-height: inherit!important; + padding: 0!important; +} + +.select2-container--default .select2-selection--multiple .select2-selection__choice, +.select2-container .select2-search--inline .select2-search__field { + margin-top: 0!important; +} + +.popover { + border: 1px solid #ebebeb; + border-radius: 0; + box-shadow: none; + padding: 0; +} + +.popover-title { + border-radius: 0; +} + +.popover.top > .arrow { + border-top-color: #ebebeb; +} + +.popover.left > .arrow { + border-left-color: #ebebeb; +} + +.popover.right > .arrow { + border-right-color: #ebebeb; +} + +.popover.bottom > .arrow { + border-bottom-color: #ebebeb; +} + +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + border-radius: 0!important; +} + +.bootstrap-tagsinput { + background: #fff; + border-radius: 0; + border: 1px solid #dce1e4; + box-shadow: none!important; + font-size: 13px; + padding: 6px 10px!important; + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + width: 100%; + margin: 0; +} + +.bootstrap-tagsinput .tag { + line-height: inherit; +} + +.input-group-addon { + border-radius: 0!important; + background: #f1f1f1; + border-color: #dce1e4; +} + +.bootstrap-timepicker-widget input { + background: #fff; + border-radius: 0; + border: 1px solid #dce1e4; + box-shadow: none!important; + font-size: 13px; + padding: 6px 10px!important; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + width: 45px!important; +} + +.bootstrap-timepicker-widget input:focus { + border: 1px solid #bdc5c9; + background: #fff; +} + +.bootstrap-timepicker-widget .icon-chevron-up:before { + font-family: FontAwesome; + content: "\f106"; + font-style: normal; +} + +.bootstrap-timepicker-widget .icon-chevron-down:before { + font-family: FontAwesome; + content: "\f107"; + font-style: normal; +} + +.bootstrap-timepicker-widget a { + text-decoration: none; +} + +/* Tables */ + +.table > tbody > tr > td, +.table > tbody > tr > th, +.table > tfoot > tr > td, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > thead > tr > th, +.table td { + padding: 15px!important; +} + + +tr.group, +tr.group:hover { + background-color: #ddd !important; +} + + + + +/* Center */ + +.center { + margin: 0 auto; + float: none!important; + display: block; +} + + +/* Display */ + +.display-block { + display: block; +} + +.display-inline { + display: inline-block; +} + + +/* Middle Box */ + +.box-middle { + position: absolute; + height: 400px; + width: 400px; + top: 50%; + left: 50%; + margin-left: -200px!important; + margin-top: -200px!important; +} + + +/* Header */ + +.navbar { + border: none; + background: #FFF; + padding: 0px; + height: 60px; + margin: 0px; + z-index: 999; + border-radius: 0px; + border: none; + margin: auto; + position: relative; + -webkit-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); + box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.1); +} + +.page-header-fixed .navbar { + position: fixed; + right: 0; + left: 0; +} + +@media (min-width: 768px) { + .page-content.container .navbar { + width: 750px; + } +} + +@media (min-width: 992px) { + .page-content.container .navbar { + width: 970px; + } +} + +@media (min-width: 1200px) { + .page-content.container .navbar { + width: 1170px; + } +} + +/* logo */ + +.navbar .logo-box { + position: relative; + width: 160px; + height: 60px; + float: left; + display: table; +} + +.navbar .logo-box .logo-text { + font-size: 20px; + font-weight: bold; + line-height: 60px; + padding: 0 15px 0 15px; + vertical-align: middle; + display: table-cell; + text-align: center; +} + +.navbar .logo-box a:hover, +.navbar .logo-box a:focus { + text-decoration: none; +} + +.navbar .logo-box a { + margin: 0 auto; +} + +.small-sidebar .navbar .logo-box { + width: 65px; +} + + +/* Top Menu */ + +.navbar-nav.navbar-right { + margin-right: 0; +} + +.top-menu .navbar-nav > .nav-item { + height: 49px; +} + +.top-menu .navbar-nav a.nav-link { + display: block; + padding: 20px 18px; + color: #5f5f5f; + border: none; + position: relative; + line-height: 20px; +} + +.top-menu .nav .nav-item .nav-link:hover, +.top-menu .nav .nav-item .nav-link:focus, +.top-menu .nav .nav-item .nav-link:active, +.top-menu .nav .open .nav-link, +.top-menu .nav .open .nav-link:hover, +.top-menu .nav .open .nav-link:focus { + background: transparent; +} + +.top-menu .nav .open .nav-link, +.top-menu .nav .open .nav-link:hover, +.top-menu .nav .open .nav-link:focus { + background: transparent; + border-color: none; +} + +.top-menu .navbar-nav .nav-item .nav-link i { + font-size: 14px; +} + +.top-menu .navbar-nav .nav-item .nav-link .badge { + font-family: 'Spoqa Han Sans',"Helvetica Neue",Helvetica,Arial,sans-serif; + position: absolute; + top: 12px; + right: 7px; + padding: 3px 6px; + font-size: 11px; + text-shadow: 0 1px 0 rgba(0,0,0,0.3); +} + +.top-menu .navbar-nav .nav-item .nav-link .user-name { + padding: 0 10px 0 0; + line-height: 20px; +} + +.top-menu .navbar-nav .nav-item .nav-link .user-name { + padding: 0 10px 0 0; + line-height: 20px; +} + +@media (max-width: 991px) { + .top-menu .navbar-nav .nav-item .nav-link .user-name { + display: none; + } +} + +.top-menu .navbar-nav .nav-item .nav-link .user-name > i { + margin-left: 5px; +} + +.avatar { + padding: 0px; + margin: -19px 0 -15px 0; + position: relative; + display: inline-block; +} + + +.nav .open > nav-link, +.nav .open > nav-link:hover, +.nav .open > nav-link:focus { + background-color: #eee; + border-color: transparent; +} + +.navbar .dropdown .dropdown-menu { + display: block; + visibility: hidden; + opacity: 0; + transition: all 300ms ease; + -moz-transition: all 300ms ease; + -webkit-transition: all 300ms ease; + -o-transition: all 300ms ease; + -ms-transition: all 300ms ease; + margin-top: 40px!important; +} + +.navbar .open .dropdown-menu { + visibility: visible; + opacity: 1; + margin-top: 25px!important; +} + +.navbar .dropdown { + display: inline-block; +} + + + +/* Page Content */ + +.page-content { + -webkit-box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.3); + -moz-box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.3); + box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.3); + background: #f7f8f8; + min-height: 100%; +} + +.page-content.container { + padding-left: 0px; + padding-right: 0px; +} + + + +/* Page Inner */ + +.page-inner { + padding: 0 0 50px 0; + background: #F1F4F9; + position: relative; +} + + +.page-header-fixed .page-inner { + padding: 60px 0 50px 0; +} + + + +.page-title { + background: #e9edf2; + border-bottom: 1px solid #dee2e8; + + padding: 20px; +} + + +.page-title h3 { + font-size: 24px; + font-weight: 300; + color: #74767d; + padding: 0px; + margin: 0 0 4px 0; +} + + +/* Page Settings */ + +.page-breadcrumb .breadcrumb { + float: left; + background: transparent; + padding: 0px; + margin-top: 30px; +} + +.page-breadcrumb ol.breadcrumb { + margin: 0px; +} + +.page-breadcrumb ol.breadcrumb li.breadcrumb-item a { + font-size: 13px; + color: #90999c; +} + +.page-breadcrumb ol.breadcrumb li.breadcrumb-item.active { + font-size: 13px; + color: #90999c; +} + +.page-breadcrumb ul.breadcrumb { + margin: 0px; +} + +.page-breadcrumb ul.breadcrumb li.breadcrumb-item { + float: left; + display: inline; +} + +.page-breadcrumb ul.breadcrumb li.breadcrumb-item a { + font-size: 13px; + color: #90999c; +} + + +/* Main Wrapper */ + +#main-wrapper { + margin: 20px; + padding: 0px; +} + + +/* Footer */ + +.page-footer { + background: #fff; + width: 100%; + display: block; + position: absolute; + bottom: 0; + padding-left: 25px; + padding-right: 25px; + padding-top: 19px; + padding-bottom: 19px; +} + + + +/* Icons */ +/* FontAwesome */ + +.fontawesome-icon-list .fa-item { + padding: 10px 20px 10px 20px; + color: #333; +} + +.fontawesome-icon-list .fa-item i { + margin-right: 5px; +} + +.fontawesome-icon-list .fa-item:hover { + background: #f1f1f1; +} + + + + +/* Extra */ + +.page-error #main-wrapper { + margin: 5%; +} + +.page-error .details { + margin-bottom: 20px; + text-align: center; +} + +/* Login */ + +.page-login #main-wrapper, +.page-lock-screen #main-wrapper { + margin: 5%; +} + +.login-box { + margin: auto; + max-width: 400px; +} + +.login-box .logo-name { + display: block; + font-size: 22px; + font-weight: bold; + text-decoration: none; + color: #6c6c6c; +} + +.login-box .user-box { + display: block; + clear: both; + overflow: hidden; +} + +.login-box .user-box img { + width: 60px; + height: 60px; + display: block; + margin: 0 auto; +} + +.login-box .user-box form { + overflow: hidden; +} + + +/* Login alt */ + +.login-alt .login-box { + max-width: 100%; +} + +.login-info { + margin-top: 19px; +} + + + +/* Transitions */ + +.top-menu .navbar-nav .nav-item .nav-link .badge, +.menu li a .arrow:before, +.menu li.open > a > .arrow:before { + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + -o-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +} + + +/* Overflow */ + +.navbar .logo-box, +.navbar .logo-box a, +.top-menu .navbar-nav > .nav-item.nav-link > img, +.info, +.page-inner, +.page-breadcrumb, +.page-breadcrumb .breadcrumb, +.page-breadcrumb ul, +.info-box, +.text-box, +.page-footer{ + overflow: hidden; +} + +@media (max-width: 767px) { + .navbar .logo-box { + margin: 0 auto; + background: transparent!important; + text-align: center; + width: 100%!important; + border: 0!important; + } + + .navbar .logo-box a { + color: #5F5F5F!important; + } + + .navbar .logo-box .logo-text { + width: 100%; + display: inline-block!important; + } + + .top-menu { + display: none; + } + + .page-inner { + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + -o-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; + } + +} diff --git a/asset/static/stylesheets/common/modern.min.css b/asset/static/stylesheets/common/modern.min.css new file mode 100755 index 0000000..ba144c1 --- /dev/null +++ b/asset/static/stylesheets/common/modern.min.css @@ -0,0 +1 @@ +body{position:relative;height:100%!important;width:100%;font-family:'Spoqa Han Sans',"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;background:#ccc;color:#4E5E6A}html{height:100%!important;position:relative}:hover,:active,:focus{outline:none!important}p{display:block;font-size:13px;font-weight:400;letter-spacing:normal;line-height:22px;margin:0 0 10px;font-style:normal;white-space:normal}h1,h2,h3,h4,h5,h6{font-weight:300}h1{font-size:30px}h2{font-size:24px}h3{font-size:16px}h4{font-size:14px}h5{font-size:12px}h6{font-size:10px}h3,h4,h5{font-weight:600}.f-thin{font-weight:300}.f-normal{font-weight:400}.f-bold{font-weight:600}.f-s-10{font-size:10px}.f-s-11{font-size:11px}.f-s-12{font-size:12px}.f-s-13{font-size:13px}.f-s-14{font-size:14px}.f-s-15{font-size:15px}.f-s-16{font-size:16px}.f-s-17{font-size:17px}.f-s-18{font-size:18px}.f-s-20{font-size:20px}.f-s-22{font-size:22px}.f-s-24{font-size:24px}.f-s-26{font-size:26px}.f-s-28{font-size:28px}.f-s-30{font-size:30px}.f-s-32{font-size:32px}.text-xs{font-size:10px}.text-sm{font-size:12px}.text-md{font-size:16px}.text-lg{font-size:32px}.text-xl{font-size:52px}.text-xxl{font-size:80px}.f-white{color:#fff}.f-gray{color:#ccc}.f-gray-dark{color:#a2a2a2}.f-black{color:#333}.f-green{color:#22BAA0}.f-blue{color:#127acb}.f-lblue{color:#12AFCB}.f-purple{color:#7a6fbe}.f-red{color:#f25656}.f-yellow{color:#f6d433}.f-orange{color:#e79b2f}.text-default{color:#ccc}.text-primary{color:#7a6fbe}.text-success{color:#22BAA0}.text-info{color:#12AFCB}.text-warning{color:#f6d433}.text-danger{color:#f25656}.icon-xs{font-size:12px}.icon-sm{font-size:14px}.icon-md{font-size:16px}.icon-lg{font-size:18px}.icon-state-default{color:#ccc}.icon-state-primary{color:#7a6fbe}.icon-state-success{color:#22BAA0}.icon-state-info{color:#12AFCB}.icon-state-warning{color:#f6d433}.icon-state-danger{color:#f25656}.alert{border-radius:0;padding-top:10px;padding-bottom:10px;border:0}.alert-success{background:#e5f3df}.alert-info{background:#d3e6f0}.alert-warning{background:#f6f2dd}.alert-danger{background:#f1d9d9}.badge{-webkit-border-radius:12px!important;-moz-border-radius:12px!important;border-radius:12px!important;border-radius:0;font-weight:300;font-size:11px!important;text-align:center;vertical-align:middle;line-height:11px!important;height:18px;padding:3px 6px;text-shadow:none!important}.badge.badge-roundless{-webkit-border-radius:0!important;-moz-border-radius:0!important;border-radius:0!important}.badge.badge-default{background:#f1f1f1;color:#aaa}.badge.badge-primary{background:#7a6fbe;color:#FFF}.badge.badge-info{background:#12AFCB;color:#FFF}.badge.badge-success{background:#22BAA0;color:#FFF}.badge.badge-danger{background:#f25656;color:#FFF}.badge.badge-warning{background:#f6d433;color:#FFF}.no-s{margin:0!important;padding:0!important}.no-m{margin:0}.no-p{padding:0}.m{margin:15px}.m-t-xxs{margin-top:5px}.m-r-xxs{margin-right:5px}.m-b-xxs{margin-bottom:5px}.m-l-xxs{margin-left:5px}.m-t-xs{margin-top:10px}.m-r-xs{margin-right:10px}.m-b-xs{margin-bottom:10px}.m-l-xs{margin-left:10px}.m-t-sm{margin-top:15px}.m-r-sm{margin-right:15px}.m-b-sm{margin-bottom:15px}.m-l-sm{margin-left:15px}.m-t-md{margin-top:20px}.m-r-md{margin-right:20px}.m-b-md{margin-bottom:20px}.m-l-md{margin-left:20px}.m-t-lg{margin-top:25px}.m-r-lg{margin-right:25px}.m-b-lg{margin-bottom:25px}.m-l-lg{margin-left:25px}.m-t-xxl{margin-top:30px}.m-r-xxl{margin-right:30px}.m-b-xxl{margin-bottom:30px}.m-l-xxl{margin-left:30px}.m-t-n-xxs{margin-top:-5px}.m-r-n-xxs{margin-right:-5px}.m-b-n-xxs{margin-bottom:-5px}.m-l-n-xxs{margin-left:-5px}.m-t-n-xs{margin-top:-10px}.m-r-n-xs{margin-right:-10px}.m-b-n-xs{margin-bottom:-10px}.m-l-n-xs{margin-left:-10px}.m-t-n-sm{margin-top:-15px}.m-r-n-sm{margin-right:-15px}.m-b-n-sm{margin-bottom:-15px}.m-l-n-sm{margin-left:-15px}.m-t-n-md{margin-top:-20px}.m-r-n-md{margin-right:-20px}.m-b-n-md{margin-bottom:-20px}.m-l-n-md{margin-left:-20px}.m-t-n-lg{margin-top:-25px}.m-r-n-lg{margin-right:-25px}.m-b-n-lg{margin-bottom:-25px}.m-l-n-lg{margin-left:-25px}.m-t-n-xxl{margin-top:-30px}.m-r-n-xxl{margin-right:-30px}.m-b-n-xxl{margin-bottom:-30px}.m-l-n-xxl{margin-left:-30px}.p{padding:15px}.p-h-xxs{padding-left:5px;padding-right:5px}.p-h-xs{padding-left:10px;padding-right:10px}.p-h-sm{padding-left:15px;padding-right:15px}.no-p-h{padding-left:0;padding-right:0}.no-p-v{padding-top:0;padding-bottom:0}.p-h-md{padding-left:20px;padding-right:20px}.p-h-lg{padding-left:25px;padding-right:25px}.p-h-xxl{padding-left:30px;padding-right:30px}.p-v-xxs{padding-top:5px;padding-bottom:5px}.p-v-xs{padding-top:10px;padding-bottom:10px}.p-v-sm{padding-top:15px;padding-bottom:15px}.p-v-md{padding-top:20px;padding-bottom:20px}.p-v-lg{padding-top:25px;padding-bottom:25px}.p-v-xxl{padding-top:30px;padding-bottom:30px}.no-b{border:0!important}.b{border:1px solid #f1f1f1}.b-t{border-top:1px solid #f1f1f1}.b-r{border-right:1px solid #f1f1f1}.b-b{border-bottom:1px solid #f1f1f1}.b-l{border-left:1px solid #f1f1f1}.b-default{border-color:#f1f1f1}.b-primary{border-color:#7a6fbe}.b-info{border-color:#12AFCB}.b-success{border-color:#22BAA0}.b-warning{border-color:#f6d433}.b-danger{border-color:#f25656}.b-2{border-size:2px}.b-3{border-size:3px}.b-4{border-size:4px}.b-n-t{border-top:0}.b-n-r{border-right:0}.b-n-b{border-bottom:0}.b-n-l{border-left:0}.no-r{border-radius:0!important}.r{border-radius:2px}.r-t-l{border-top-left-radius:2px}.r-t-r{border-top-right-radius:2px}.r-b-l{border-bottom-left-radius:2px}.r-b-r{border-bottom-right-radius:2px}.no-r-t-l{border-top-left-radius:0!important}.no-r-t-r{border-top-right-radius:0!important}.no-r-b-l{border-bottom-left-radius:0!important}.no-r-b-r{border-bottom-right-radius:0!important}.bg-n{background:transparent!important}.bg-primary{background-color:#7a6fbe;color:#fff}.bg-primary.dark{background-color:#6e63b4;color:#fff}.bg-primary.light{background-color:#877cc7;color:#fff}.bg-success{background-color:#22BAA0;color:#fff}.bg-success.dark{background-color:#1da890;color:#fff}.bg-success.light{background-color:#32c6ad;color:#fff}.bg-info{background-color:#12AFCB;color:#fff}.bg-info.dark{background-color:#0ba0bb;color:#fff}.bg-info.light{background-color:#20beda;color:#fff}.bg-warning{background-color:#f6d433;color:#fff}.bg-warning.dark{background-color:#f1ca11;color:#fff}.bg-warning.light{background-color:#fada44;color:#fff}.bg-danger{background-color:#f25656;color:#fff}.bg-danger.dark{background-color:#e54f4f;color:#fff}.bg-danger.light{background-color:#f66d6d;color:#fff}.bg-dark{background-color:#333;color:#fff}.bg-dark.dark{background-color:#2b2b2b;color:#fff}.bg-dark.light{background-color:#3b3b3b;color:#fff}.bg-light{background-color:#f1f1f1}.bg-light.dark{background-color:#e5e5e5}.bg-light.light{background-color:#f9f9f9}.bg-gray{background-color:#ccc}.bg-gray.dark{background-color:#b9b9b9}.bg-gray.light{background-color:#d7d7d7}.btn{font-size:13px;border:1px solid transparent;border-radius:0;outline:none!important}.btn-addon i{position:relative;float:left;width:35px;height:35px;margin:-7px -13px;margin-right:12px;line-height:34px;text-align:center;border-top-left-radius:2px;border-bottom-left-radius:2px;background-color:rgba(0,0,0,0.1)}.btn-rounded.btn-addon i{margin:-7px -16px;margin-right:15px;border-radius:50px}.btn-rounded.btn-addon.btn-sm i{margin:-7px -16px;margin-right:10px;border-radius:50px}.btn-lg{line-height:inherit}.btn-lg.btn-addon i{width:45px;height:45px;margin:-11px -17px;margin-right:16px;line-height:45px}.btn-sm.btn-addon i{width:30px;height:30px;margin:-6px -11px;margin-right:10px;line-height:30px}.btn-xs.btn-addon i{width:22px;height:22px;margin:-2px -6px;margin-right:5px;line-height:22px;font-size:10px}.btn-rounded{padding-left:15px;padding-right:15px;border-radius:50px}.btn-group.open .dropdown-toggle{box-shadow:none}.btn-default{background-color:#fff;color:#333;border:1px solid #e5e5e5}.btn-default:focus,.btn-default.focus{color:#333;background-color:#f1f1f1;border-color:#e5e5e5}.btn-default:hover{color:#333;background-color:#f1f1f1;border-color:#e5e5e5}.btn-default:active,.btn-default.active,.open > .dropdown-toggle.btn-default{color:#333;background-color:#f1f1f1;border-color:#e5e5e5}.btn-default:active:hover,.btn-default.active:hover,.open > .dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open > .dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open > .dropdown-toggle.btn-default.focus{color:#333;background-color:#f1f1f1;border-color:#e5e5e5}.btn-default:active,.btn-default.active,.open > .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#7a6fbe;border-color:transparent}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#6a5fac;border-color:transparent}.btn-primary:hover{color:#fff;background-color:#6a5fac;border-color:transparent}.btn-primary:active,.btn-primary.active,.open > .dropdown-toggle.btn-primary{color:#fff;background-color:#6a5fac;border-color:transparent}.btn-primary:active:hover,.btn-primary.active:hover,.open > .dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open > .dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open > .dropdown-toggle.btn-primary.focus{color:#fff;background-color:#6a5fac;border-color:transparent}.btn-primary:active,.btn-primary.active,.open > .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#6a5fac;border-color:transparent}.btn-primary .badge{color:#6a5fac;background-color:#fff}.btn-success{color:#fff;background-color:#22BAA0;border-color:transparent}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#1DB198;border-color:transparent}.btn-success:hover{color:#fff;background-color:#1DB198;border-color:transparent}.btn-success:active,.btn-success.active,.open > .dropdown-toggle.btn-success{color:#fff;background-color:#1DB198;border-color:transparent}.btn-success:active:hover,.btn-success.active:hover,.open > .dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open > .dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open > .dropdown-toggle.btn-success.focus{color:#fff;background-color:#1DB198;border-color:transparent}.btn-success:active,.btn-success.active,.open > .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#1DB198;border-color:transparent}.btn-success .badge{color:#1DB198;background-color:#fff}.btn-info{color:#fff;background-color:#12AFCB;border-color:transparent}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#08A7C3;border-color:transparent}.btn-info:hover{color:#fff;background-color:#08A7C3;border-color:transparent}.btn-info:active,.btn-info.active,.open > .dropdown-toggle.btn-info{color:#fff;background-color:#08A7C3;border-color:transparent}.btn-info:active:hover,.btn-info.active:hover,.open > .dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open > .dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open > .dropdown-toggle.btn-info.focus{color:#fff;background-color:#08A7C3;border-color:transparent}.btn-info:active,.btn-info.active,.open > .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#08A7C3;border-color:transparent}.btn-info .badge{color:#12AFCB;background-color:#fff}.btn-warning{color:#fff;background-color:#f2ca4c;border-color:transparent}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#e8bf40;border-color:transparent}.btn-warning:hover{color:#fff;background-color:#e8bf40;border-color:transparent}.btn-warning:active,.btn-warning.active,.open > .dropdown-toggle.btn-warning{color:#fff;background-color:#e8bf40;border-color:transparent}.btn-warning:active:hover,.btn-warning.active:hover,.open > .dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open > .dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open > .dropdown-toggle.btn-warning.focus{color:#fff;background-color:#e8bf40;border-color:transparent}.btn-warning:active,.btn-warning.active,.open > .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#e8bf40;border-color:transparent}.btn-warning .badge{color:#f2ca4c;background-color:#fff}.btn-danger{color:#fff;background-color:#f25656;border-color:transparent}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#e14444;border-color:transparent}.btn-danger:hover{color:#fff;background-color:#e14444;border-color:transparent}.btn-danger:active,.btn-danger.active,.open > .dropdown-toggle.btn-danger{color:#fff;background-color:#e14444;border-color:transparent}.btn-danger:active:hover,.btn-danger.active:hover,.open > .dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open > .dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open > .dropdown-toggle.btn-danger.focus{color:#fff;background-color:#e14444;border-color:transparent}.btn-danger:active,.btn-danger.active,.open > .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#e14444;border-color:transparent}.btn-danger .badge{color:#f25656;background-color:#fff}.btn-facebook{background:#627AAC;color:#fff}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook:active{background:#3B5998;color:#fff}.btn-twitter{background:#33BBF3;color:#fff}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter:active{background:#00ABF0;color:#fff}.btn-google{background:#E0745B;color:#fff}.btn-google:hover,.btn-google:focus,.btn-google:active{background:#D95232;color:#fff}.btn-youtube{background:#D6464B;color:#fff}.btn-youtube:hover,.btn-youtube:focus,.btn-youtube:active{background:#CC181E;color:#fff}.btn-vimeo{background:#69C8FF;color:#fff}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo:active{background:#4BF;color:#fff}.btn-dribbble{background:#E094B7;color:#fff}.btn-dribbble:hover,.btn-dribbble:focus,.btn-dribbble:active{background:#D97AA5;color:#fff}.btn-github{background:#848484;color:#fff}.btn-github:hover,.btn-github:focus,.btn-github:active{background:#666;color:#fff}.btn-instagram{background:#658EAF;color:#fff}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram:active{background:#3F729B;color:#fff}.btn-pinterest{background:#BE464B;color:#fff}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest:active{background:#AE181F;color:#fff}.btn-vk{background:#7D9BBB;color:#fff}.btn-vk:hover,.btn-vk:focus,.btn-vk:active{background:#5D83AA;color:#fff}.btn-rss{background:#F19958;color:#fff}.btn-rss:hover,.btn-rss:focus,.btn-rss:active{background:#EE802F;color:#fff}.btn-flickr{background:#3395C4;color:#fff}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr:active{background:#007BB6;color:#fff}.bs-n{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.bs-dark{-webkit-box-shadow:0 0 3px rgba(0,0,0,.6);-moz-box-shadow:0 0 3px rgba(0,0,0,.6);box-shadow:0 0 3px rgba(0,0,0,.6)}.bs-light{-webkit-box-shadow:0 0 3px rgba(0,0,0,.3);-moz-box-shadow:0 0 3px rgba(0,0,0,.3);box-shadow:0 0 3px rgba(0,0,0,.3)}.bs-t{-webkit-box-shadow:0 -1px 1px rgba(0,0,0,.05);-moz-box-shadow:0 -1px 1px rgba(0,0,0,.05);box-shadow:0 -1px 1px rgba(0,0,0,.05)}.bs-r{-webkit-box-shadow:1px 0 1px rgba(0,0,0,.05);-moz-box-shadow:1px 0 1px rgba(0,0,0,.05);box-shadow:1px 0 1px rgba(0,0,0,.05)}.bs-b{-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);-moz-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.bs-l{-webkit-box-shadow:-1px 0 1px rgba(0,0,0,.05);-moz-box-shadow:-1px 0 1px rgba(0,0,0,.05);box-shadow:-1px 0 1px rgba(0,0,0,.05)}.full-height{height:100%!important}.full-width{width:100%!important}.w-xxs{width:50px}.w-xs{width:90px}.w-sm{width:140px}.w{width:200px}.w-md{width:240px}.w-lg{width:280px}.w-xl{width:330px}.w-xxl{width:370px}.w-auto{width:auto}.h-auto{height:auto}.tooltip-inner{border-radius:0}.panel{-webkit-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);-moz-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);border:0!important;margin-bottom:25px;border-radius:0}@media (min-width: 768px){.panel > .row > div:first-child{padding-left:15px;padding-right:0}.panel > .row > div:last-child{padding-left:0;padding-right:15px}}.panel .card-header{padding:20px;overflow:hidden;border-top-left-radius:0;border-top-right-radius:0;border:0!important;height:55px;font-size:14px;font-weight:600}.panel .card-header .panel-title{font-size:14px;float:left;margin:0;padding:0;font-weight:600}.panel .card-header .panel-title small{font-size:80%}.panel .card-header .panel-control{float:right;height:auto}.panel .card-header .panel-control a{text-decoration:none;color:#ccc;margin-left:5px;font-size:14px;float:left}.panel .card-header .panel-control a:hover{color:#a2a2a2}.panel .panel-body{position:relative;padding:20px;border-bottom-left-radius:0;border-bottom-right-radius:0}.panel .card-header + .panel-body{padding:0 20px 20px}.panel-default .card-header{background:#f1f1f1;border-color:#e7e7e7}.panel-default .card-header .panel-control a{color:#bbb}.panel-default .card-header .panel-control a:hover{color:#a2a2a2}.panel-primary .card-header{background:#7a6fbe;color:#fff}.panel-primary .card-header .panel-control a{color:#fff}.panel-primary .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-success .panel-heading{background:#22BAA0;color:#fff}.panel-success .panel-heading .panel-control a{color:#fff}.panel-success .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-info .panel-heading{background:#12AFCB;color:#fff}.panel-info .panel-heading .panel-control a{color:#fff}.panel-info .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-warning .panel-heading{background:#f6d433;color:#fff}.panel-warning .panel-heading .panel-control a{color:#fff}.panel-warning .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-danger .panel-heading{background:#f25656;color:#fff}.panel-danger .panel-heading .panel-control a{color:#fff}.panel-danger .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-transparent{background:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.panel-transparent .panel-heading .panel-control a{color:#ccc}.panel-transparent .panel-heading .panel-control a:hover{color:#a2a2a2}.panel-white{background:#fff}.panel-white .panel-heading .panel-control a{color:#ccc}.panel-white .panel-heading .panel-control a:hover{color:#a2a2a2}.panel-purple{background:#7a6fbe}.panel-purple .panel-heading{color:#fff}.panel-purple .panel-body{color:#fff}.panel-purple .panel-heading .panel-control a{color:#fff}.panel-purple .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-green{background:#22BAA0}.panel-green .panel-heading{color:#fff}.panel-green .panel-body{color:#fff}.panel-green .panel-heading .panel-control a{color:#fff}.panel-green .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-blue{background:#12AFCB}.panel-blue .panel-heading{color:#fff}.panel-blue .panel-body{color:#fff}.panel-blue .panel-heading .panel-control a{color:#fff}.panel-blue .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-yellow{background:#f6d433}.panel-yellow .panel-heading{color:#fff}.panel-yellow .panel-body{color:#fff}.panel-yellow .panel-heading .panel-control a{color:#fff}.panel-yellow .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-red{background:#f25656}.panel-red .panel-heading{color:#fff}.panel-red .panel-body{color:#fff}.panel-red .panel-heading .panel-control a{color:#fff}.panel-red .panel-heading .panel-control a:hover{color:#f1f1f1}.panel-placeholder{border:2px dashed #ddd;margin-bottom:20px}.well{border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;background-color:#F6F6F6;border:0}.modal{z-index:9999}.modal-content{-webkit-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);-moz-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);border:0;border-radius:0}.modal-header{padding:20px;overflow:hidden;border-top-left-radius:0;border-top-right-radius:0;border:0!important;height:55px;font-size:14px;font-weight:600}.modal-body{position:relative;padding:20px;border-bottom-left-radius:0;border-bottom-right-radius:0}.modal-footer{position:relative;padding:20px;border-bottom-left-radius:0;border-bottom-right-radius:0;border:0}.modal-header + .modal-body{padding:0 20px 20px}.modal-body + .modal-footer{padding:0 20px 20px}.modal-open{overflow-y:auto!important;padding:0!important}.modal-backdrop{z-index:999}.pagination > li > a{color:#5B5B5B}.pagination > .active > a,.pagination > .active > span,.pagination > .active > a:hover,.pagination > .active > span:hover,.pagination > .active > a:focus,.pagination > .active > span:focus{background:#22BAA0;border-color:#22BAA0}.progress{border-radius:2px}.progress-squared{border-radius:0}.progress-xs{height:5px}.progress-sm{height:10px}.progress-md{height:15px}.progress-lg{height:25px}.progress-bar{background-color:#7a6fbe}.progress-bar-success{background-color:#22BAA0}.progress-bar-info{background-color:#12AFCB}.progress-bar-warning{background-color:#f6d433}.progress-bar-danger{background-color:#f25656}.tab-content{padding:15px;background:#fff}.nav-tabs > li > a{border-radius:0!important;color:#777;border-bottom:1px solid #DDD}.nav-tabs > li > a:hover{background:#f1f1f1}.nav-tabs > li.active > a,.nav-tabs > li.active > a:hover,.nav-tabs > li.active > a:focus{color:#555;cursor:default;background-color:#fff;border-bottom-color:#fff}.nav-pills > li > a{color:#777;border-radius:0!important}.nav-pills > li.active > a,.nav-pills > li.active > a:hover,.nav-pills > li.active > a:focus{color:#fff;background-color:#7a6fbe}.tabs-below > .nav-tabs,.tabs-right > .nav-tabs,.tabs-left > .nav-tabs{border-bottom:0}.tab-content > .tab-pane,.pill-content > .pill-pane{display:none}.tab-content > .active,.pill-content > .active{display:block}.tabs-below > .nav-tabs{border-top:1px solid #ddd}.tabs-below > .nav-tabs > li{margin-top:-1px;margin-bottom:0}.tabs-below > .nav-tabs > li > a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-below > .nav-tabs > li > a:hover,.tabs-below > .nav-tabs > li > a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below > .nav-tabs > .active > a,.tabs-below > .nav-tabs > .active > a:hover,.tabs-below > .nav-tabs > .active > a:focus{border-color:#fff #ddd #ddd}.tabs-left > .nav-tabs > li,.tabs-right > .nav-tabs > li{float:none}.tabs-left > .nav-tabs > li > a,.tabs-right > .nav-tabs > li > a{min-width:74px;margin-right:0;margin-bottom:3px;border-bottom:0}.tabs-left > .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left > .nav-tabs > li > a{margin-right:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-left > .nav-tabs > li > a:hover,.tabs-left > .nav-tabs > li > a:focus{border-color:#eee #ddd #eee #eee}.tabs-left > .nav-tabs .active > a,.tabs-left > .nav-tabs .active > a:hover,.tabs-left > .nav-tabs .active > a:focus{border-color:#ddd transparent #ddd #ddd;border-right-color:#fff;border-bottom:1px solid #DDD}.tabs-right > .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right > .nav-tabs > li > a{margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-right > .nav-tabs > li > a:hover,.tabs-right > .nav-tabs > li > a:focus{border-color:#eee #eee #eee #ddd}.tabs-right > .nav-tabs .active > a,.tabs-right > .nav-tabs .active > a:hover,.tabs-right > .nav-tabs .active > a:focus{border-color:#ddd #ddd #ddd transparent;border-left-color:#fff;border-bottom:1px solid #DDD}.panel-group .panel-heading .panel-title > a{font-size:14px}.panel-group .panel-heading{font-size:14px;height:auto!important}.panel-group .panel-heading .panel-title > a{text-decoration:none}.panel-group .panel-heading{border-bottom:0!important}.panel > .panel-heading + .panel-collapse > .panel-body{border-top-color:transparent}.panel-group .panel-heading .panel-title{position:relative;width:100%}.label.label-default{background:#fff;border:1px solid #e5e5e5}.label.label-success{background:#22BAA0}.label.label-primary{background:#7a6fbe}.label.label-info{background:#12AFCB}.label.label-danger{background:#f25656}.label.label-warning{background:#f6d433}label{font-size:13px;font-weight:400}.controls label{display:block}.form-control{background:#fff;border-radius:0;border:1px solid #dce1e4;box-shadow:none!important;font-size:13px;padding:6px 10px!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}input[disabled]{background:#f7f7f7;border-color:#d2d7db}.form-control:focus{border:1px solid #bdc5c9;background:#fff}.help-block{margin-bottom:5px}.form-group.has-success .form-control,.form-group.has-warning .form-control,.form-group.has-error .form-control{box-shadow:none}.form-group.has-success .form-control:focus{border:1px solid #22BAA0;background:#fff}.form-group.has-warning .form-control:focus{border:1px solid #f6d433;background:#fff}.form-group.has-error .form-control:focus{border:1px solid #f25656;background:#fff}.form-group.has-success label{color:#22BAA0}.form-group.has-warning label{color:#f6d433}.form-group.has-error label{color:#f25656}label.error{color:#a94442;font-weight:700;margin-top:5px;float:left;font-size:12px}input.form-control.input-rounded{border-radius:30px}.input-group .btn{padding:7px 12px}ol.linenums{margin:0}.select2-selection{background:#fff!important;border-radius:0!important;border:1px solid #dce1e4!important;box-shadow:none!important;font-size:13px!important;padding:6px 10px!important;height:34px!important;-webkit-transition:all .2s ease-in-out!important;-moz-transition:all .2s ease-in-out!important;-o-transition:all .2s ease-in-out!important;transition:all .2s ease-in-out!important}.select2-dropdown{background:#fff;border-radius:0;border:1px solid #dce1e4;border-top:0;box-shadow:none!important;font-size:13px;padding:6px 10px!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;z-index:9999}.select2-dropdown.select2-dropdown--above{border:1px solid #dce1e4;border-bottom:0}.select2-selection--multiple .select2-selection__choice{background:#f1f1f1!important;border-radius:0!important;border:1px solid #ccc!important}.select2-container--default .select2-selection--single .select2-selection__rendered,.select2-container--default .select2-selection--multiple .select2-selection__rendered{line-height:inherit!important;padding:0!important}.select2-container--default .select2-selection--multiple .select2-selection__choice,.select2-container .select2-search--inline .select2-search__field{margin-top:0!important}.popover{border:1px solid #ebebeb;border-radius:0;box-shadow:none;padding:0}.popover-title{border-radius:0}.popover.top > .arrow{border-top-color:#ebebeb}.popover.left > .arrow{border-left-color:#ebebeb}.popover.right > .arrow{border-right-color:#ebebeb}.popover.bottom > .arrow{border-bottom-color:#ebebeb}.input-group-lg > .form-control,.input-group-lg > .input-group-addon,.input-group-lg > .input-group-btn > .btn{border-radius:0!important}.bootstrap-tagsinput{background:#fff;border-radius:0;border:1px solid #dce1e4;box-shadow:none!important;font-size:13px;padding:6px 10px!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:100%;margin:0}.bootstrap-tagsinput .tag{line-height:inherit}.input-group-addon{border-radius:0!important;background:#f1f1f1;border-color:#dce1e4}.bootstrap-timepicker-widget input{background:#fff;border-radius:0;border:1px solid #dce1e4;box-shadow:none!important;font-size:13px;padding:6px 10px!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:45px!important}.bootstrap-timepicker-widget input:focus{border:1px solid #bdc5c9;background:#fff}.bootstrap-timepicker-widget .icon-chevron-up:before{font-family:FontAwesome;content:"\f106";font-style:normal}.bootstrap-timepicker-widget .icon-chevron-down:before{font-family:FontAwesome;content:"\f107";font-style:normal}.bootstrap-timepicker-widget a{text-decoration:none}.table > tbody > tr > td,.table > tbody > tr > th,.table > tfoot > tr > td,.table > tfoot > tr > th,.table > thead > tr > td,.table > thead > tr > th,.table td{padding:15px!important}tr.group,tr.group:hover{background-color:#ddd!important}.center{margin:0 auto;float:none!important;display:block}.display-block{display:block}.display-inline{display:inline-block}.box-middle{position:absolute;height:400px;width:400px;top:50%;left:50%;margin-left:-200px!important;margin-top:-200px!important}.navbar{border:none;background:#FFF;padding:0;height:60px;margin:0;z-index:999;border-radius:0;border:none;margin:auto;position:relative;-webkit-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);-moz-box-shadow:0 5px 5px -5px rgba(0,0,0,0.1);box-shadow:0 5px 5px -5px rgba(0,0,0,0.1)}.page-header-fixed .navbar{position:fixed;right:0;left:0}@media (min-width: 768px){.page-content.container .navbar{width:750px}}@media (min-width: 992px){.page-content.container .navbar{width:970px}}@media (min-width: 1200px){.page-content.container .navbar{width:1170px}}.topmenu-outer{height:60px;background:#fff;margin-left:160px}.small-sidebar .topmenu-outer{margin-left:65px}.navbar .logo-box{position:relative;width:160px;height:60px;float:left;display:table}.navbar .logo-box .logo-text{font-size:20px;font-weight:700;line-height:60px;padding:0 15px;vertical-align:middle;display:table-cell;text-align:center}.navbar .logo-box a:hover,.navbar .logo-box a:focus{text-decoration:none}.navbar .logo-box a{margin:0 auto}.small-sidebar .navbar .logo-box{width:65px}.navbar-nav.navbar-right{margin-right:0}.top-menu .navbar-nav > li{height:49px}.top-menu .navbar-nav > li > a{display:block;padding:20px 18px;color:#5f5f5f;border:none;position:relative;line-height:20px}.top-menu .nav > li > a:hover,.top-menu .nav > li > a:focus,.top-menu .nav > li > a:active,.top-menu .nav .open > a,.top-menu .nav .open > a:hover,.top-menu .nav .open > a:focus{background:transparent}.top-menu .nav .open > a,.top-menu .nav .open > a:hover,.top-menu .nav .open > a:focus{background:transparent;border-color:none}.top-menu .navbar-nav > li > a > i{font-size:14px}.top-menu .navbar-nav > li > a > .badge{font-family:'Spoqa Han Sans',"Helvetica Neue",Helvetica,Arial,sans-serif;position:absolute;top:12px;right:7px;padding:3px 6px;font-size:11px;text-shadow:0 1px 0 rgba(0,0,0,0.3)}.top-menu .navbar-nav > li > a > .user-name{padding:0 10px 0 0;line-height:20px;padding:0 10px 0 0;line-height:20px}@media (max-width: 991px){.top-menu .navbar-nav > li > a > .user-name{display:none}}.top-menu .navbar-nav > li > a > .user-name > i{margin-left:5px}.avatar{padding:0;margin:-19px 0 -15px;position:relative;display:inline-block}.nav .open > a,.nav .open > a:hover,.nav .open > a:focus{background-color:#eee;border-color:transparent}.navbar .dropdown .dropdown-menu{display:block;visibility:hidden;opacity:0;transition:all 300ms ease;-moz-transition:all 300ms ease;-webkit-transition:all 300ms ease;-o-transition:all 300ms ease;-ms-transition:all 300ms ease;margin-top:40px!important}.navbar .open .dropdown-menu{visibility:visible;opacity:1;margin-top:25px!important}.navbar .dropdown{display:inline-block}.page-content{-webkit-box-shadow:0 0 10px 0 rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px 0 rgba(0,0,0,0.3);box-shadow:0 0 10px 0 rgba(0,0,0,0.3);background:#f7f8f8;min-height:100%}.page-content.container{padding-left:0;padding-right:0}.horizontal-bar{width:100%;display:block;z-index:9998;float:none;height:auto!important;left:0;right:0;bottom:0;height:74px}@media (min-width: 768px){.page-sidebar-fixed.page-horizontal-bar .sidebar{position:fixed;top:0;bottom:auto;padding-top:60px}}.small-sidebar .horizontal-bar .slimScrollDiv{overflow:visible!important}.page-horizontal-bar.page-header-fixed .horizontal-bar{padding-top:60px}.page-horizontal-bar.page-sidebar-fixed .navbar{z-index:9999}@media (min-width: 768px){.page-horizontal-bar.page-sidebar-fixed .page-content.container .horizontal-bar{width:750px;margin:0 auto}}@media (min-width: 992px){.page-horizontal-bar.page-sidebar-fixed .page-content.container .horizontal-bar{width:970px;margin:0 auto}}@media (min-width: 1200px){.page-horizontal-bar.page-sidebar-fixed .page-content.container .horizontal-bar{width:1170px;margin:0 auto}}@media (max-width: 1200px){.horizontal-bar .accordion-menu > li > a > p{display:none}.compact-menu .horizontal-bar .accordion-menu > li > a > p{display:none!important}body:not(.small-sidebar) .horizontal-bar .accordion-menu > li > a > .menu-icon{float:none!important;margin:0!important}.horizontal-bar .accordion-menu ul{top:50px!important}}.horizontal-bar .page-sidebar-inner{overflow:visible!important}.horizontal-bar .accordion-menu{text-align:center;font-size:0;width:100%!important;overflow:visible!important}.horizontal-bar .accordion-menu li{display:inline-block;margin:0!important;padding:0!important;position:relative}.small-sidebar.page-horizontal-bar .horizontal-bar .accordion-menu > li > a,.horizontal-bar .accordion-menu > li > a{padding:16px!important}.small-sidebar .horizontal-bar .accordion-menu li a span.menu-icon{font-size:15px}.horizontal-bar .accordion-menu > li > a > p{font-size:13px}.compact-menu .horizontal-bar .accordion-menu li a p{display:inline}.horizontal-bar .accordion-menu .sub-menu li a{font-size:13px;padding:10px;padding-left:15px;padding-right:15px}.page-horizontal-bar.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li > a{width:auto}.horizontal-bar .accordion-menu > li > a > span.arrow:before{display:none}body:not(.small-sidebar) .horizontal-bar .menu.accordion-menu > li > a > .menu-icon{font-size:14px}.small-sidebar.page-horizontal-bar .menu.accordion-menu > li > a > span.menu-icon{margin:0!important}.horizontal-bar .accordion-menu > li > ul{left:0!important;top:74px;width:200px;position:absolute}.horizontal-bar .accordion-menu ul li{display:block;text-align:left}.horizontal-bar .accordion-menu li.menu-title{display:none}.small-sidebar .horizontal-bar .accordion-menu > li > a > p{display:none!important}.small-sidebar .horizontal-bar .accordion-menu > li > ul{top:44px!important}.small-sidebar.page-horizontal-bar.page-sidebar-fixed .page-inner{padding-left:0}.small-sidebar.page-sidebar-fixed.page-header-fixed.page-horizontal-bar .page-inner{padding:110px 0 50px}.small-sidebar.page-sidebar-fixed.page-header-fixed .page-inner{padding:60px 0 50px 65px}.small-sidebar.page-sidebar-fixed:not(.page-header-fixed) .page-inner{padding:0 0 50px 65px}.small-sidebar.page-header-fixed.page-horizontal-bar:not(.page-sidebar-fixed) .page-inner{padding:0 0 50px}.page-horizontal-bar:not(.page-sidebar-fixed) .checkout{top:0}.page-horizontal-bar.page-sidebar-fixed:not(.compact-menu) .checkout{top:134px}.page-horizontal-bar.page-sidebar-fixed.compact-menu .checkout{top:111px}.menu li a .badge{margin-left:10px}.menu.accordion-menu{padding:0;margin:0;width:160px;color:#fff;position:relative;display:block}.menu.accordion-menu a{display:block;padding:15px;padding-left:18px;padding-right:18px;background:transparent;text-decoration:none;font-size:13px}.menu.accordion-menu > li > a{text-align:center}body:not(.page-horizontal-bar):not(.small-sidebar) .menu.accordion-menu a{text-align:center}.menu.accordion-menu a p{line-height:1.42857143!important;margin:0}.menu.accordion-menu a span.menu-icon{display:inline-block;font-size:20px;margin-bottom:10px}.menu.accordion-menu li > a > .arrow:before{width:10px;float:right;display:block;margin-top:-20px;font-size:16px;font-family:FontAwesome;height:auto;content:"\f104";font-weight:300}.menu.accordion-menu > li > a > .arrow:before{margin-top:-39px}.menu.accordion-menu li.open > a > .arrow:before{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.menu.accordion-menu li{list-style-type:none}.menu.accordion-menu li a .badge{float:right;margin-top:1px;margin-right:0;margin-left:0;display:block}.menu.accordion-menu ul{z-index:9999}.menu.accordion-menu ul li a{display:block;padding:10px;background:transparent;text-decoration:none;font-size:13px}.menu.accordion-menu ul li ul{padding:2px 0}.compact-menu .menu.accordion-menu .sub-menu li .sub-menu li a,.hover-menu .menu.accordion-menu .sub-menu li .sub-menu li a,.page-horizontal-bar .menu.accordion-menu .sub-menu li .sub-menu li a{padding-left:26px}.compact-menu .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li a,.hover-menu .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li a,.page-horizontal-bar .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li a{padding-left:31px}.compact-menu .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li .sub-menu li a,.hover-menu .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li .sub-menu li a,.page-horizontal-bar .menu.accordion-menu .sub-menu li .sub-menu li .sub-menu li .sub-menu li a{padding-left:36px}.menu ul{padding:10px;z-index:99}.compact-menu:not(.small-sidebar) .menu.accordion-menu li a{text-align:left!important}.compact-menu:not(.page-horizontal-bar) .menu.accordion-menu > li > a > p{display:inline!important}.compact-menu .menu.accordion-menu a span.menu-icon{display:inline-block!important;font-size:14px!important;margin-bottom:0!important;margin-right:10px!important}.compact-menu .menu.accordion-menu li a .arrow:before{margin-top:-2px}.page-horizontal-bar.compact-menu .menu.accordion-menu ul{top:50px}.page-horizontal-bar.compact-menu.small-sidebar .menu.accordion-menu ul{top:46px!important}.hover-menu:not(.page-horizontal-bar) .menu.accordion-menu > li > a > span.arrow{display:none}.hover-menu .menu.accordion-menu > li:hover > ul,.hover-menu .menu.accordion-menu > li.open:hover > ul{display:inline-block!important}.hover-menu .accordion-menu li{position:relative}.hover-menu .accordion-menu > li > ul{position:absolute;left:160px;width:200px}.hover-menu:not(.page-horizontal-bar) .accordion-menu > li > ul{position:absolute;top:0;left:160px;width:200px}.hover-menu .sidebar,.hover-menu .sidebar .page-sidebar-inner,.hover-menu .sidebar .menu,.hover-menu .sidebar .slimScrollDiv{overflow:visible!important}.hover-menu .accordion-menu ul li a{text-align:left!important}.compact-menu .accordion-menu li a p{display:inline}.hover-menu .sidebar .slimScrollBar,.hover-menu .slimScrollBar{display:none!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu{width:65px}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .page-sidebar-inner{overflow:hidden!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu{width:160px!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu > li > a{padding:15px;text-align:center}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu > li > a{padding:15px;padding-left:18px;padding-right:18px}.compact-menu.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu > li > a{text-align:left}.compact-menu.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu > li > a > .menu-icon{margin-right:10px!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu ul li a{text-align:center}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li a .menu-icon{float:none;margin:0!important;font-size:14px}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li a .menu-icon{font-size:20px}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li a p,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li a .arrow,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li.menu-title,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li a .badge{display:none!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li a p{margin:0}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .menu.accordion-menu li.open .sub-menu{visibility:hidden;height:0!important;padding:0}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .sidebar-widget,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .sidebar-header{display:block!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li a p,.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li.menu-title{display:block!important}.compact-menu.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li a p,.compact-menu.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li.menu-title{display:inline!important}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li.open .sub-menu{visibility:visible;height:auto!important;padding:10px}.small-sidebar.page-sidebar-fixed:not(.page-horizontal-bar) .sidebar:hover .menu.accordion-menu li a .arrow{display:block!important;float:right}.small-sidebar:not(.page-sidebar-fixed) .sidebar,.small-sidebar:not(.page-sidebar-fixed) .sidebar > *,.horizontal-bar,.horizontal-bar > *{overflow:visible!important}.small-sidebar:not(.page-sidebar-fixed) .sidebar .slimScrollBar,.horizontal-bar .slimScrollBar{display:none!important}.small-sidebar:not(.page-sidebar-fixed) .menu.accordion-menu{width:auto;oveflow:visible!important}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu,.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li{padding:0;margin:0}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li{list-style:none;position:relative;width:auto}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li a{text-decoration:none;display:block}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li > a{padding:15px 25px;text-align:center;position:relative;width:265px}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li a span.menu-icon{font-size:14px;margin:0 50px 0 0 !important;float:left}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li a p{margin:0;float:left}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li a .arrow:before{width:10px;float:right;margin-left:15px;margin-top:-2px;display:inline;font-size:16px;font-family:FontAwesome;height:18px;content:"\f104";font-weight:300}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li:hover > a{z-index:999}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li > ul{position:absolute;left:65px;top:48px;width:200px}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu ul li a{display:block;padding:10px!important;padding-left:15px!important;padding-right:15px!important;background:transparent;font-size:13px}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu ul li span.menu-icon{margin-right:15px}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li > a > span.arrow{display:none}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li a p{display:block;text-align:left}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu li.menu-title{display:none}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li:hover > ul,.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li.open:hover > ul{display:inline-block!important}.page-horizontal-bar .accordion-menu > li:hover > ul,.page-horizontal-bar .accordion-menu > li.open:hover > ul{display:inline-block!important}.small-sidebar:not(.page-sidebar-fixed) .accordion-menu > li.open > ul{display:none!important}.page-horizontal-bar .accordion-menu > li.open > ul{display:none!important}.page-inner{padding:0 0 50px;background:#F1F4F9;position:relative}.page-header-fixed:not(.page-sidebar-fixed):not(.page-horizontal-bar) .page-inner{padding:60px 0 50px}.page-sidebar-fixed.page-header-fixed .page-inner{padding:60px 0 50px 160px}.page-horizontal-bar.page-sidebar-fixed.page-header-fixed .page-inner{padding:134px 0 50px}.page-horizontal-bar.page-sidebar-fixed.page-header-fixed.compact-menu .page-inner{padding:111px 0 50px}.page-sidebar-fixed:not(.page-header-fixed) .page-inner{padding:0 0 50px 160px}.small-sidebar.page-sidebar-fixed.page-header-fixed .page-inner{padding:60px 0 50px 65px}.small-sidebar.page-sidebar-fixed:not(.page-header-fixed) .page-inner{padding:0 0 50px 65px}.small-sidebar.page-header-fixed:not(.page-sidebar-fixed) .page-inner{padding:60px 0 50px}.page-title{background:#e9edf2;border-bottom:1px solid #dee2e8;padding:20px}.page-title h3{font-size:24px;font-weight:300;color:#74767d;padding:0;margin:0 0 4px}.page-breadcrumb .breadcrumb{float:left;background:transparent;padding:0;margin-top:30px}.page-breadcrumb ol.breadcrumb{margin:0}.page-breadcrumb ol.breadcrumb li a{font-size:13px;color:#90999c}.page-breadcrumb ol.breadcrumb li.active{font-size:13px;color:#90999c}.page-breadcrumb ul{margin:0}.page-breadcrumb ul li{float:left;display:inline}.page-breadcrumb ul li a{font-size:13px;color:#90999c}#main-wrapper{margin:20px;padding:0}.page-footer{background:#fff;width:100%;display:block;position:absolute;bottom:0;padding:19px 25px}.fontawesome-icon-list .fa-item{padding:10px 20px;color:#333}.fontawesome-icon-list .fa-item i{margin-right:5px}.fontawesome-icon-list .fa-item:hover{background:#f1f1f1}.page-error #main-wrapper{margin:5%}.page-error .details{margin-bottom:20px;text-align:center}.page-login #main-wrapper,.page-register #main-wrapper,.page-forgot #main-wrapper,.page-lock-screen #main-wrapper{margin:5%}.login-box{margin:auto;max-width:400px}.login-box .logo-name{display:block;font-size:22px;font-weight:700;text-decoration:none;color:#6c6c6c}.login-box .user-box{display:block;clear:both;overflow:hidden}.login-box .user-box img{width:60px;height:60px;display:block;margin:0 auto}.login-box .user-box form{overflow:hidden}.login-alt .login-box{max-width:100%}.login-info{margin-top:19px}.top-menu .navbar-nav > li > a > .badge,.menu li a .arrow:before,.menu li.open > a > .arrow:before{-webkit-transition:all .1s ease-in-out;-moz-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}.navbar .logo-box,.navbar .logo-box a,.top-menu .navbar-nav > li > a > img,.info,.messages li a,.messages li a .msg-img,.messages li a .msg-text,.messages li a .msg-time,.tasks li a,.tasks li a .task-icon,.search-form,body:not(.small-sidebar):not(.page-horizontal-bar) .menu.accordion-menu,.page-inner,.small-sidebar .page-sidebar-fixed .page-inner,.page-breadcrumb,.page-breadcrumb .breadcrumb,.page-breadcrumb ul,.info-box,.text-box,.small-sidebar .accordion-menu li a,.page-footer,.color-switcher{overflow:hidden}@media (max-width: 767px){.navbar .logo-box{margin:0 auto;background:transparent!important;text-align:center;width:100%!important;border:0!important}.navbar .logo-box a{color:#5F5F5F!important}.navbar .logo-box .logo-text{width:100%;display:inline-block!important}.top-menu{display:none}.page-inner{-webkit-transition:all .1s ease-in-out;-moz-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}} \ No newline at end of file diff --git a/asset/static/views/widgets/modal.html b/asset/static/views/widgets/modal.html new file mode 100644 index 0000000..1618c91 --- /dev/null +++ b/asset/static/views/widgets/modal.html @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/asset/template/layout/base.html b/asset/template/layout/base.html new file mode 100644 index 0000000..c47028c --- /dev/null +++ b/asset/template/layout/base.html @@ -0,0 +1,77 @@ + + + + + + In-house service + + + + + + + + + + + + + + + + + + + + + + + + + + + {% block style_area %} + + + + + + + + + {% endblock %} + + + +{% block body_area %}{% endblock %} +{% block script_area %} + +{% endblock %} + + + \ No newline at end of file diff --git a/asset/template/views/base.html b/asset/template/views/base.html new file mode 100644 index 0000000..a125e85 --- /dev/null +++ b/asset/template/views/base.html @@ -0,0 +1,83 @@ +{% extends "/layout/base.html" %} {% block body_area %} + + +
            + + + +
            +
            +
            +
            +

            {{ title }}

            + +
            +
            + {% block extra_head_content %}{% endblock %} +
            +
            +
            +
            + {% block content_area %}{% endblock %} + +
            + + {% block footer_area %} {% endblock %} + + +
            + +
            + +{% endblock %} \ No newline at end of file diff --git a/asset/template/views/change_password.html b/asset/template/views/change_password.html new file mode 100644 index 0000000..1547446 --- /dev/null +++ b/asset/template/views/change_password.html @@ -0,0 +1,116 @@ +{% extends "base.html" %} +{% block script_area %} +{{ block.Super|safe }} + + + +{% endblock %} +{% block content_area %} +
            +
            +
            +
            +
            +
            + + +
            +

            {{user_id}}

            +

            +
            +
            +
            + + +
            + +
            +
            + +
            + + +
            + +
            +
            + +
            + + +
            + +
            +
            +
            +
            +
            +
            + + + +
            +
            +
            +
            +
            +
            +
            +{% endblock %} \ No newline at end of file diff --git a/asset/template/views/error.html b/asset/template/views/error.html new file mode 100644 index 0000000..b2b0fcf --- /dev/null +++ b/asset/template/views/error.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% block content_area %} +
            +
            +

            {{ code }} +

            +
            +

            {{ message }}

            +

            오류가 발생하거나 허용되지않은 동작입니다.

            +

            뒤로 가시거나 + + 으로 이동해주세요.

            +
            +
            +
            + +{% endblock %} diff --git a/asset/template/views/index.html b/asset/template/views/index.html new file mode 100644 index 0000000..657683f --- /dev/null +++ b/asset/template/views/index.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% block content_area %} +
            +
            +
            +
            +

            +

            홈홈

            +
            +
            +
            +
            +{% endblock %} \ No newline at end of file diff --git a/asset/template/views/login.html b/asset/template/views/login.html new file mode 100644 index 0000000..a9b8e19 --- /dev/null +++ b/asset/template/views/login.html @@ -0,0 +1,111 @@ +{% extends "base.html" %} +{% block script_area %} +{{ block.Super|safe }} + + + +{% endblock %} +{% block content_area %} +
            + +
            +{% endblock %} \ No newline at end of file diff --git a/bench.py b/bench.py new file mode 100755 index 0000000..ebf64bc --- /dev/null +++ b/bench.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +import os +import re +import time + +def report(c, lines): + rtv = [] + for str in lines: + str=re.sub("^[ \t]+",'', str) + if str.find("Latency") == 0 or str.find("Requests/sec") == 0: + token = re.split("[ \t]+", str) + value = re.sub("[^0-9\.]", '', token[1]) + if re.match("[0-9\.]+us", token[1]): + rtv.append(float(value)/1000) + elif re.match("[0-9\.]+s", token[1]): + rtv.append(float(value)*1000) + else: + rtv.append(float(value)) + print c,"\t", rtv[0],"\t",rtv[1] + +def run(cmd): + stdin, stdout, stderr = os.popen3(cmd) + return stdout.readlines() + +offset = 5 +maxConcurrency = offset * 61 +duration = 10 +for num in range(1, maxConcurrency/offset): + concurrency = num * offset + thread = 16 if concurrency > 16 else concurrency + cmd = ( +'''wrk --timeout 7 -t %d -c %d -d %d http://localhost:8080/api/v1/media/admin/2/thumb''' + % (thread, concurrency, duration)) + result =run(cmd) + report(concurrency, result) + time.sleep(5) diff --git a/changer-dev.service b/changer-dev.service new file mode 100644 index 0000000..f123261 --- /dev/null +++ b/changer-dev.service @@ -0,0 +1,28 @@ +[Unit] +Description=Inhouse internal user mgnt server +Documentation=https://amuz.es +After=syslog.target network-online.target +Wants=network-online.target + +[Service] +Type=notify +Restart=always +RestartSec=15 +ExecStart=/usr/bin/changer -C /etc/changer/settings.yml -L /var/logs/changer +WorkingDirectory=/var/logs/changer +#ExecReload=/bin/kill -s HUP $MAINPID +TimeoutStartSec=5 + + +# Disable timeout logic and wait until process is stopped +TimeoutStopSec=0 +# SIGTERM signal is used to stop Minio +KillSignal=SIGTERM +SendSIGKILL=no + +SuccessExitStatus=0 +# kill only the docker process, not all processes in the cgroup +KillMode=process + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/enums/user_type.go b/enums/user_type.go new file mode 100644 index 0000000..7a3479f --- /dev/null +++ b/enums/user_type.go @@ -0,0 +1,47 @@ +package enums + +import ( + "errors" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" +) + +type UserType string + +const ( + UserTypeAnon UserType = "ROLE_ANONYMOUS" + UserTypeUser UserType = "ROLE_USER" + UserTypeAdmin UserType = "ROLE_ADMIN" +) + +func UserTypeNameOf(value string) (UserType, error) { + switch value { + case "ROLE_USER": + return UserTypeUser, nil + case "ROLE_ADMIN": + return UserTypeAdmin, nil + } + return UserTypeAnon, errors.New("unable to find UserType") +} + +func (status UserType) Name() string { + return string(status) +} + +func (status UserType) String() string { + switch status { + case UserTypeUser: + return "사용자" + case UserTypeAdmin: + return "관리자" + } + return "로그인 안함" +} + +func (status UserType) MarshalEasyJSON(w *jwriter.Writer) { + w.String(string(status)) +} +func (status *UserType) UnmarshalEasyJSON(w *jlexer.Lexer) { + *status, _ = UserTypeNameOf(w.String()) +} diff --git a/http/iface/metric_count.go b/http/iface/metric_count.go new file mode 100644 index 0000000..a85bf32 --- /dev/null +++ b/http/iface/metric_count.go @@ -0,0 +1,64 @@ +package iface + +import ( + "strconv" + "time" +) + +//turns a new initialized CounterMetric object. +func NewCounterMetric() *CounterMetric { + ca := &CounterMetric{} + ca.Inc = make(chan Tuple) + ca.internalRequestsSum = 0 + ca.internalRequests = make(map[string]uint64, 0) + ca.internalRequestCodes = make(map[string]uint64, 0) + return ca +} + +// StartTimer will call a forever loop in a goroutine to calculate +// metrics for measurements every d ticks. The parameter of this +// function should normally be 1 * time.Minute, if not it will expose +// unintuive JSON keys (requests_per_minute and +// request_sum_per_minute). +func (ca *CounterMetric) StartTimer(d time.Duration) { + timer := time.Tick(d) + go func() { + for { + select { + case tup := <-ca.Inc: + ca.internalRequestsSum++ + ca.internalRequests[tup.Path]++ + ca.internalRequestCodes[strconv.FormatInt(int64(tup.Code), 10)]++ + case <-timer: + ca.reset() + } + } + }() +} + +// GetStats to fulfill aspects.Aspect interface, it returns the data +// that will be served as JSON. +func (ca *CounterMetric) GetStats() interface{} { + return *ca +} + +// Name to fulfill aspects.Aspect interface, it will return the name +// of the JSON object that will be served. +func (ca *CounterMetric) Name() string { + return "Counter" +} + +// InRoot to fulfill aspects.Aspect interface, it will return where to +// put the JSON object into the monitoring endpoint. +func (ca *CounterMetric) InRoot() bool { + return false +} + +func (ca *CounterMetric) reset() { + ca.RequestsSum = ca.internalRequestsSum + ca.Requests = ca.internalRequests + ca.RequestCodes = ca.internalRequestCodes + ca.internalRequestsSum = 0 + ca.internalRequests = make(map[string]uint64, ca.RequestsSum) + ca.internalRequestCodes = make(map[string]uint64, len(ca.RequestCodes)) +} diff --git a/http/iface/metric_duration.go b/http/iface/metric_duration.go new file mode 100644 index 0000000..ed2c216 --- /dev/null +++ b/http/iface/metric_duration.go @@ -0,0 +1,118 @@ +package iface + +import ( + "math" + "sort" + "time" +) + +type RequestDurationAggr struct { + lastMinuteRequestTimes []float64 + Min float64 `json:"min"` + Max float64 `json:"max"` + Mean float64 `json:"mean"` + Stdev float64 `json:"stdev"` + P90 float64 `json:"p90"` + P95 float64 `json:"p95"` + P99 float64 `json:"p99"` + Timestamp time.Time `json:"timestamp"` +} + +// NewRequestDurationAggr returns a new initialized RequestDurationAggr +// object. +func NewRequestDurationAggr() *RequestDurationAggr { + rt := &RequestDurationAggr{} + rt.lastMinuteRequestTimes = make([]float64, 0) + rt.Timestamp = time.Now() + return rt +} + +// StartTimer will call a forever loop in a goroutine to calculate +// metrics for measurements every d ticks. +func (rt *RequestDurationAggr) StartTimer(d time.Duration) { + timer := time.Tick(d) + go func() { + for { + <-timer + rt.calculate() + } + }() +} + +// GetStats to fulfill Metrics.Metric interface, it returns the data +// that will be served as JSON. +func (rt *RequestDurationAggr) GetStats() interface{} { + return rt +} + +// Name to fulfill Metrics.Metric interface, it will return the name +// of the JSON object that will be served. +func (rt *RequestDurationAggr) Name() string { + return "RequestTime" +} + +// InRoot to fulfill Metrics.Metric interface, it will return where to +// put the JSON object into the monitoring endpoint. +func (rt *RequestDurationAggr) InRoot() bool { + return false +} + +func (rt *RequestDurationAggr) Add(n float64) { + rt.lastMinuteRequestTimes = append(rt.lastMinuteRequestTimes, n) +} + +func (rt *RequestDurationAggr) calculate() { + sortedSlice := rt.lastMinuteRequestTimes[:] + rt.lastMinuteRequestTimes = make([]float64, 0) + l := len(sortedSlice) + if l <= 1 { + return + } + sort.Float64s(sortedSlice) + + rt.Timestamp = time.Now() + rt.Min = sortedSlice[0] + rt.Max = sortedSlice[l - 1] + rt.Mean = mean(sortedSlice, l) + rt.Stdev = correctedStdev(sortedSlice, rt.Mean, l) + rt.P90 = p90(sortedSlice, l) + rt.P95 = p95(sortedSlice, l) + rt.P99 = p99(sortedSlice, l) +} + +func mean(orderedObservations []float64, l int) float64 { + res := 0.0 + for i := 0; i < l; i++ { + res += orderedObservations[i] + } + + return res / float64(l) +} + +func p90(orderedObservations []float64, l int) float64 { + return percentile(orderedObservations, l, 0.9) +} + +func p95(orderedObservations []float64, l int) float64 { + return percentile(orderedObservations, l, 0.95) +} + +func p99(orderedObservations []float64, l int) float64 { + return percentile(orderedObservations, l, 0.99) +} + +// percentile with argument p \in (0,1), l is the length of given orderedObservations +// It does a simple apporximation of an ordered list of observations. +// Formula: sortedSlice[0.95*length(sortedSlice)] +func percentile(orderedObservations []float64, l int, p float64) float64 { + return orderedObservations[int(p * float64(l))] +} + +func correctedStdev(observations []float64, mean float64, l int) float64 { + var omega float64 + for i := 0; i < l; i++ { + omega += math.Pow(observations[i]-mean, 2) + } + stdev := math.Sqrt(1 / (float64(l) - 1) * omega) + return stdev +} diff --git a/http/iface/rest.go b/http/iface/rest.go new file mode 100644 index 0000000..8aaf0ed --- /dev/null +++ b/http/iface/rest.go @@ -0,0 +1,236 @@ +//go:generate ${GOPATH}/bin/easyjson $GOFILE +package iface + +import ( + "bytes" + "time" + + "amuz.es/gogs/infra/changer/enums" +) + +//easyjson:json +type Login struct { + Id string `form:"id" json:"id" binding:"required"` + Password string `form:"password" json:"password" binding:"required"` + RedirectTo string `form:"redirect_to" json:"redirect_to,omitempty"` +} + +//easyjson:json +type ChangePassword struct { + OldPassword string `form:"old_password" json:"old_password" binding:"required"` + Password string `form:"password" json:"password" binding:"required"` + PasswordConfirm string `form:"password_confirm" json:"password_confirm" binding:"required"` +} + +//easyjson:json +type Token struct { + Token string `json:"token"` + Expire string `json:"expire"` +} + +//easyjson:json +type LoginResponse struct { + Message string `json:"message"` + RedirectTo string `json:"redirectTo,omitempty"` +} + +//easyjson:json +type WrappedResponse struct { + Message string `json:"message"` + Content interface{} `json:"content,omitempty"` +} + +//easyjson:json +type NewId struct { + Id interface{} `json:"id" binding:"required"` +} + +//easyjson:json +type NameCodePair struct { + Name string `json:"name" binding:"required"` + Code string `json:"code" binding:"required"` +} + +//easyjson:json +type KeyValuePair struct { + Key string `json:"key" binding:"required"` + Value string `json:"value" binding:"required"` +} + +//easyjson:json +type Tuple struct { + Path string + Code int +} + +//easyjson:json +type CounterMetric struct { + Inc chan Tuple `json:"-"` + internalRequestsSum uint64 + internalRequests map[string]uint64 + internalRequestCodes map[string]uint64 + RequestsSum uint64 `json:"request_sum_per_minute"` + Requests map[string]uint64 `json:"requests_per_minute"` + RequestCodes map[string]uint64 `json:"request_codes_per_minute"` +} + +//easyjson:json +type DurationMetricReadable struct { + Min string `json:"min"` + Max string `json:"max"` + Mean string `json:"mean"` + Stdev string `json:"stdev"` + P90 string `json:"p90"` + P95 string `json:"p95"` + P99 string `json:"p99"` + + Timestamp time.Time `json:"timestamp"` +} + +//easyjson:json +type DurationMetric struct { + Min uint64 `json:"min"` + Max uint64 `json:"max"` + Mean uint64 `json:"mean"` + Stdev uint64 `json:"stdev"` + P90 uint64 `json:"p90"` + P95 uint64 `json:"p95"` + P99 uint64 `json:"p99"` + Timestamp time.Time `json:"timestamp"` +} + +//easyjson:json +type RequestMetricReadable struct { + Duration DurationMetricReadable `json:"duration"` + Count CounterMetric `json:"count"` +} + +//easyjson:json +type RequestMetric struct { + Duration DurationMetric `json:"duration"` + Count CounterMetric `json:"count"` +} + +//easyjson:json +type RuntimeMetric struct { + GoVersion string `json:"go_version"` + GoOs string `json:"go_os"` + GoArch string `json:"go_arch"` + CpuNum int `json:"cpu_num"` + GoroutineNum int `json:"goroutine_num"` + Gomaxprocs int `json:"go_maxprocs"` + CgoCallNum int64 `json:"cgo_call_num"` +} + +//easyjson:json +type MemoryMetric struct { + MemAllocated uint64 `json:"mem_allocated"` + MemTotal uint64 `json:"mem_total"` + MemSys uint64 `json:"mem_sys"` + Lookups uint64 `json:"lookups"` + MemMallocs uint64 `json:"mem_mallocs"` + MemFrees uint64 `json:"mem_frees"` + + HeapAlloc uint64 `json:"heap_alloc"` + HeapSys uint64 `json:"heap_sys"` + HeapIdle uint64 `json:"heap_idle"` + HeapInuse uint64 `json:"heap_inuse"` + HeapReleased uint64 `json:"heap_released"` + HeapObjects uint64 `json:"heap_objects"` + + StackInuse uint64 `json:"stack_inuse"` + StackSys uint64 `json:"stack_sys"` + MSpanInuse uint64 `json:"m_span_inuse"` + MSpanSys uint64 `json:"m_span_sys"` + MCacheInuse uint64 `json:"m_cache_inuse"` + MCacheSys uint64 `json:"m_cache_sys"` + BuckHashSys uint64 `json:"buck_hash_sys"` + GCSys uint64 `json:"gc_sys"` + OtherSys uint64 `json:"other_sys"` + + NextGC uint64 `json:"next_gc"` + LastGC uint64 `json:"last_gc"` + PauseTotalNs uint64 `json:"pause_total_ns"` + PauseNs uint64 `json:"pause_ns"` + NumGC uint32 `json:"num_gc"` +} + +//easyjson:json +type Metric struct { + Cmdline []string `json:"cmd_line"` + Uptime uint64 `json:"uptime"` + Request RequestMetric `json:"request"` + Runtime RuntimeMetric `json:"runtime"` + Memory MemoryMetric `json:"memory"` +} + +//easyjson:json +type PermRes struct { + code int `json:"-" binding:"required"` + Message string `json:"message" binding:"required"` +} + +//easyjson:json +type MemoryMetricReadable struct { + MemAllocated string `json:"mem_allocated"` + MemTotal string `json:"mem_total"` + MemSys string `json:"mem_sys"` + Lookups uint64 `json:"lookups"` + MemMallocs uint64 `json:"mem_mallocs"` + MemFrees uint64 `json:"mem_frees"` + + HeapAlloc string `json:"heap_alloc"` + HeapSys string `json:"heap_sys"` + HeapIdle string `json:"heap_idle"` + HeapInuse string `json:"heap_inuse"` + HeapReleased string `json:"heap_released"` + HeapObjects uint64 `json:"heap_objects"` + + StackInuse string `json:"stack_inuse"` + StackSys string `json:"stack_sys"` + MSpanInuse string `json:"m_span_inuse"` + MSpanSys string `json:"m_span_sys"` + MCacheInuse string `json:"m_cache_inuse"` + MCacheSys string `json:"m_cache_sys"` + BuckHashSys string `json:"buck_hash_sys"` + GCSys string `json:"gc_sys"` + OtherSys string `json:"other_sys"` + + NextGC string `json:"next_gc"` + LastGC string `json:"last_gc"` + PauseTotalNs string `json:"pause_total_ns"` + PauseNs string `json:"pause_ns"` + NumGC uint32 `json:"num_gc"` +} + +//easyjson:json +type MetricReadable struct { + Cmdline []string `json:"cmd_line"` + Uptime string `json:"uptime"` + Request RequestMetricReadable `json:"request"` + Runtime RuntimeMetric `json:"runtime"` + Memory MemoryMetricReadable `json:"memory"` +} + +//easyjson:json +type UserData struct { + Id string `json:"id" binding:"required"` + Name string `json:"name" binding:"required"` + Mail string `json:"mail" binding:"required"` + Role enums.UserType `json:"role" binding:"required"` +} + +func (detail *UserData) String() string { + var buffer bytes.Buffer + buffer.WriteString("UserData(") + if detail != nil { + buffer.WriteString("id:") + buffer.WriteString(detail.Id) + } else { + buffer.WriteString("nil") + } + buffer.WriteString(")") + return buffer.String() +} + +// -vars="mem:memory.mem_allocated,duration:request.duration.min,duration:request.duration.max,duration:request.duration.mean,duration:request.duration.stdev,duration:request.duration.p90,duration:request.duration.p95,duration:request.duration.p99,mem:memory.mem_allocated,mem:memory.heap_alloc,mem:memory.heap_inuse,mem:memory.stack_inuse,duration:memory.next_gc,duration:memory.last_gc,duration:memory.pause_total_ns,duration:memory.pause_ns" diff --git a/http/iface/rest_easyjson.go b/http/iface/rest_easyjson.go new file mode 100644 index 0000000..73be53e --- /dev/null +++ b/http/iface/rest_easyjson.go @@ -0,0 +1,2330 @@ +// AUTOGENERATED FILE: easyjson marshaller/unmarshallers. + +package iface + +import ( + json "encoding/json" + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface(in *jlexer.Lexer, out *UserData) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "id": + out.Id = string(in.String()) + case "name": + out.Name = string(in.String()) + case "mail": + out.Mail = string(in.String()) + case "role": + (out.Role).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface(out *jwriter.Writer, in UserData) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"id\":") + out.String(string(in.Id)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"name\":") + out.String(string(in.Name)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mail\":") + out.String(string(in.Mail)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"role\":") + (in.Role).MarshalEasyJSON(out) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v UserData) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v UserData) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *UserData) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *UserData) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface1(in *jlexer.Lexer, out *MetricReadable) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "cmd_line": + if in.IsNull() { + in.Skip() + out.Cmdline = nil + } else { + in.Delim('[') + if !in.IsDelim(']') { + out.Cmdline = make([]string, 0, 4) + } else { + out.Cmdline = []string{} + } + for !in.IsDelim(']') { + var v1 string + v1 = string(in.String()) + out.Cmdline = append(out.Cmdline, v1) + in.WantComma() + } + in.Delim(']') + } + case "uptime": + out.Uptime = string(in.String()) + case "request": + (out.Request).UnmarshalEasyJSON(in) + case "runtime": + (out.Runtime).UnmarshalEasyJSON(in) + case "memory": + (out.Memory).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface1(out *jwriter.Writer, in MetricReadable) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"cmd_line\":") + if in.Cmdline == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v2, v3 := range in.Cmdline { + if v2 > 0 { + out.RawByte(',') + } + out.String(string(v3)) + } + out.RawByte(']') + } + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"uptime\":") + out.String(string(in.Uptime)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"request\":") + (in.Request).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"runtime\":") + (in.Runtime).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"memory\":") + (in.Memory).MarshalEasyJSON(out) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v MetricReadable) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface1(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v MetricReadable) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface1(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *MetricReadable) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface1(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *MetricReadable) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface1(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface2(in *jlexer.Lexer, out *MemoryMetricReadable) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "mem_allocated": + out.MemAllocated = string(in.String()) + case "mem_total": + out.MemTotal = string(in.String()) + case "mem_sys": + out.MemSys = string(in.String()) + case "lookups": + out.Lookups = uint64(in.Uint64()) + case "mem_mallocs": + out.MemMallocs = uint64(in.Uint64()) + case "mem_frees": + out.MemFrees = uint64(in.Uint64()) + case "heap_alloc": + out.HeapAlloc = string(in.String()) + case "heap_sys": + out.HeapSys = string(in.String()) + case "heap_idle": + out.HeapIdle = string(in.String()) + case "heap_inuse": + out.HeapInuse = string(in.String()) + case "heap_released": + out.HeapReleased = string(in.String()) + case "heap_objects": + out.HeapObjects = uint64(in.Uint64()) + case "stack_inuse": + out.StackInuse = string(in.String()) + case "stack_sys": + out.StackSys = string(in.String()) + case "m_span_inuse": + out.MSpanInuse = string(in.String()) + case "m_span_sys": + out.MSpanSys = string(in.String()) + case "m_cache_inuse": + out.MCacheInuse = string(in.String()) + case "m_cache_sys": + out.MCacheSys = string(in.String()) + case "buck_hash_sys": + out.BuckHashSys = string(in.String()) + case "gc_sys": + out.GCSys = string(in.String()) + case "other_sys": + out.OtherSys = string(in.String()) + case "next_gc": + out.NextGC = string(in.String()) + case "last_gc": + out.LastGC = string(in.String()) + case "pause_total_ns": + out.PauseTotalNs = string(in.String()) + case "pause_ns": + out.PauseNs = string(in.String()) + case "num_gc": + out.NumGC = uint32(in.Uint32()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface2(out *jwriter.Writer, in MemoryMetricReadable) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_allocated\":") + out.String(string(in.MemAllocated)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_total\":") + out.String(string(in.MemTotal)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_sys\":") + out.String(string(in.MemSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"lookups\":") + out.Uint64(uint64(in.Lookups)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_mallocs\":") + out.Uint64(uint64(in.MemMallocs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_frees\":") + out.Uint64(uint64(in.MemFrees)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_alloc\":") + out.String(string(in.HeapAlloc)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_sys\":") + out.String(string(in.HeapSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_idle\":") + out.String(string(in.HeapIdle)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_inuse\":") + out.String(string(in.HeapInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_released\":") + out.String(string(in.HeapReleased)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_objects\":") + out.Uint64(uint64(in.HeapObjects)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stack_inuse\":") + out.String(string(in.StackInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stack_sys\":") + out.String(string(in.StackSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_span_inuse\":") + out.String(string(in.MSpanInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_span_sys\":") + out.String(string(in.MSpanSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_cache_inuse\":") + out.String(string(in.MCacheInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_cache_sys\":") + out.String(string(in.MCacheSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"buck_hash_sys\":") + out.String(string(in.BuckHashSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"gc_sys\":") + out.String(string(in.GCSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"other_sys\":") + out.String(string(in.OtherSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"next_gc\":") + out.String(string(in.NextGC)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"last_gc\":") + out.String(string(in.LastGC)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"pause_total_ns\":") + out.String(string(in.PauseTotalNs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"pause_ns\":") + out.String(string(in.PauseNs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"num_gc\":") + out.Uint32(uint32(in.NumGC)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v MemoryMetricReadable) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface2(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v MemoryMetricReadable) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface2(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *MemoryMetricReadable) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface2(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *MemoryMetricReadable) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface2(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface3(in *jlexer.Lexer, out *PermRes) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "message": + out.Message = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface3(out *jwriter.Writer, in PermRes) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"message\":") + out.String(string(in.Message)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v PermRes) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface3(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v PermRes) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface3(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *PermRes) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface3(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *PermRes) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface3(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface4(in *jlexer.Lexer, out *Metric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "cmd_line": + if in.IsNull() { + in.Skip() + out.Cmdline = nil + } else { + in.Delim('[') + if !in.IsDelim(']') { + out.Cmdline = make([]string, 0, 4) + } else { + out.Cmdline = []string{} + } + for !in.IsDelim(']') { + var v4 string + v4 = string(in.String()) + out.Cmdline = append(out.Cmdline, v4) + in.WantComma() + } + in.Delim(']') + } + case "uptime": + out.Uptime = uint64(in.Uint64()) + case "request": + (out.Request).UnmarshalEasyJSON(in) + case "runtime": + (out.Runtime).UnmarshalEasyJSON(in) + case "memory": + (out.Memory).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface4(out *jwriter.Writer, in Metric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"cmd_line\":") + if in.Cmdline == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v5, v6 := range in.Cmdline { + if v5 > 0 { + out.RawByte(',') + } + out.String(string(v6)) + } + out.RawByte(']') + } + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"uptime\":") + out.Uint64(uint64(in.Uptime)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"request\":") + (in.Request).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"runtime\":") + (in.Runtime).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"memory\":") + (in.Memory).MarshalEasyJSON(out) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v Metric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface4(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v Metric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface4(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *Metric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface4(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *Metric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface4(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface5(in *jlexer.Lexer, out *MemoryMetric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "mem_allocated": + out.MemAllocated = uint64(in.Uint64()) + case "mem_total": + out.MemTotal = uint64(in.Uint64()) + case "mem_sys": + out.MemSys = uint64(in.Uint64()) + case "lookups": + out.Lookups = uint64(in.Uint64()) + case "mem_mallocs": + out.MemMallocs = uint64(in.Uint64()) + case "mem_frees": + out.MemFrees = uint64(in.Uint64()) + case "heap_alloc": + out.HeapAlloc = uint64(in.Uint64()) + case "heap_sys": + out.HeapSys = uint64(in.Uint64()) + case "heap_idle": + out.HeapIdle = uint64(in.Uint64()) + case "heap_inuse": + out.HeapInuse = uint64(in.Uint64()) + case "heap_released": + out.HeapReleased = uint64(in.Uint64()) + case "heap_objects": + out.HeapObjects = uint64(in.Uint64()) + case "stack_inuse": + out.StackInuse = uint64(in.Uint64()) + case "stack_sys": + out.StackSys = uint64(in.Uint64()) + case "m_span_inuse": + out.MSpanInuse = uint64(in.Uint64()) + case "m_span_sys": + out.MSpanSys = uint64(in.Uint64()) + case "m_cache_inuse": + out.MCacheInuse = uint64(in.Uint64()) + case "m_cache_sys": + out.MCacheSys = uint64(in.Uint64()) + case "buck_hash_sys": + out.BuckHashSys = uint64(in.Uint64()) + case "gc_sys": + out.GCSys = uint64(in.Uint64()) + case "other_sys": + out.OtherSys = uint64(in.Uint64()) + case "next_gc": + out.NextGC = uint64(in.Uint64()) + case "last_gc": + out.LastGC = uint64(in.Uint64()) + case "pause_total_ns": + out.PauseTotalNs = uint64(in.Uint64()) + case "pause_ns": + out.PauseNs = uint64(in.Uint64()) + case "num_gc": + out.NumGC = uint32(in.Uint32()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface5(out *jwriter.Writer, in MemoryMetric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_allocated\":") + out.Uint64(uint64(in.MemAllocated)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_total\":") + out.Uint64(uint64(in.MemTotal)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_sys\":") + out.Uint64(uint64(in.MemSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"lookups\":") + out.Uint64(uint64(in.Lookups)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_mallocs\":") + out.Uint64(uint64(in.MemMallocs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mem_frees\":") + out.Uint64(uint64(in.MemFrees)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_alloc\":") + out.Uint64(uint64(in.HeapAlloc)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_sys\":") + out.Uint64(uint64(in.HeapSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_idle\":") + out.Uint64(uint64(in.HeapIdle)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_inuse\":") + out.Uint64(uint64(in.HeapInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_released\":") + out.Uint64(uint64(in.HeapReleased)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"heap_objects\":") + out.Uint64(uint64(in.HeapObjects)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stack_inuse\":") + out.Uint64(uint64(in.StackInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stack_sys\":") + out.Uint64(uint64(in.StackSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_span_inuse\":") + out.Uint64(uint64(in.MSpanInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_span_sys\":") + out.Uint64(uint64(in.MSpanSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_cache_inuse\":") + out.Uint64(uint64(in.MCacheInuse)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"m_cache_sys\":") + out.Uint64(uint64(in.MCacheSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"buck_hash_sys\":") + out.Uint64(uint64(in.BuckHashSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"gc_sys\":") + out.Uint64(uint64(in.GCSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"other_sys\":") + out.Uint64(uint64(in.OtherSys)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"next_gc\":") + out.Uint64(uint64(in.NextGC)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"last_gc\":") + out.Uint64(uint64(in.LastGC)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"pause_total_ns\":") + out.Uint64(uint64(in.PauseTotalNs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"pause_ns\":") + out.Uint64(uint64(in.PauseNs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"num_gc\":") + out.Uint32(uint32(in.NumGC)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v MemoryMetric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface5(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v MemoryMetric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface5(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *MemoryMetric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface5(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *MemoryMetric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface5(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface6(in *jlexer.Lexer, out *RuntimeMetric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "go_version": + out.GoVersion = string(in.String()) + case "go_os": + out.GoOs = string(in.String()) + case "go_arch": + out.GoArch = string(in.String()) + case "cpu_num": + out.CpuNum = int(in.Int()) + case "goroutine_num": + out.GoroutineNum = int(in.Int()) + case "go_maxprocs": + out.Gomaxprocs = int(in.Int()) + case "cgo_call_num": + out.CgoCallNum = int64(in.Int64()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface6(out *jwriter.Writer, in RuntimeMetric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"go_version\":") + out.String(string(in.GoVersion)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"go_os\":") + out.String(string(in.GoOs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"go_arch\":") + out.String(string(in.GoArch)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"cpu_num\":") + out.Int(int(in.CpuNum)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"goroutine_num\":") + out.Int(int(in.GoroutineNum)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"go_maxprocs\":") + out.Int(int(in.Gomaxprocs)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"cgo_call_num\":") + out.Int64(int64(in.CgoCallNum)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v RuntimeMetric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface6(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v RuntimeMetric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface6(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *RuntimeMetric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface6(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *RuntimeMetric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface6(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface7(in *jlexer.Lexer, out *RequestMetric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "duration": + (out.Duration).UnmarshalEasyJSON(in) + case "count": + (out.Count).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface7(out *jwriter.Writer, in RequestMetric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"duration\":") + (in.Duration).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"count\":") + (in.Count).MarshalEasyJSON(out) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v RequestMetric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface7(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v RequestMetric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface7(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *RequestMetric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface7(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *RequestMetric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface7(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface8(in *jlexer.Lexer, out *RequestMetricReadable) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "duration": + (out.Duration).UnmarshalEasyJSON(in) + case "count": + (out.Count).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface8(out *jwriter.Writer, in RequestMetricReadable) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"duration\":") + (in.Duration).MarshalEasyJSON(out) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"count\":") + (in.Count).MarshalEasyJSON(out) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v RequestMetricReadable) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface8(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v RequestMetricReadable) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface8(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *RequestMetricReadable) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface8(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *RequestMetricReadable) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface8(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface9(in *jlexer.Lexer, out *DurationMetric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "min": + out.Min = uint64(in.Uint64()) + case "max": + out.Max = uint64(in.Uint64()) + case "mean": + out.Mean = uint64(in.Uint64()) + case "stdev": + out.Stdev = uint64(in.Uint64()) + case "p90": + out.P90 = uint64(in.Uint64()) + case "p95": + out.P95 = uint64(in.Uint64()) + case "p99": + out.P99 = uint64(in.Uint64()) + case "timestamp": + if data := in.Raw(); in.Ok() { + in.AddError((out.Timestamp).UnmarshalJSON(data)) + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface9(out *jwriter.Writer, in DurationMetric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"min\":") + out.Uint64(uint64(in.Min)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"max\":") + out.Uint64(uint64(in.Max)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mean\":") + out.Uint64(uint64(in.Mean)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stdev\":") + out.Uint64(uint64(in.Stdev)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p90\":") + out.Uint64(uint64(in.P90)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p95\":") + out.Uint64(uint64(in.P95)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p99\":") + out.Uint64(uint64(in.P99)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"timestamp\":") + out.Raw((in.Timestamp).MarshalJSON()) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v DurationMetric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface9(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v DurationMetric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface9(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *DurationMetric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface9(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *DurationMetric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface9(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface10(in *jlexer.Lexer, out *DurationMetricReadable) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "min": + out.Min = string(in.String()) + case "max": + out.Max = string(in.String()) + case "mean": + out.Mean = string(in.String()) + case "stdev": + out.Stdev = string(in.String()) + case "p90": + out.P90 = string(in.String()) + case "p95": + out.P95 = string(in.String()) + case "p99": + out.P99 = string(in.String()) + case "timestamp": + if data := in.Raw(); in.Ok() { + in.AddError((out.Timestamp).UnmarshalJSON(data)) + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface10(out *jwriter.Writer, in DurationMetricReadable) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"min\":") + out.String(string(in.Min)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"max\":") + out.String(string(in.Max)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"mean\":") + out.String(string(in.Mean)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"stdev\":") + out.String(string(in.Stdev)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p90\":") + out.String(string(in.P90)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p95\":") + out.String(string(in.P95)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"p99\":") + out.String(string(in.P99)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"timestamp\":") + out.Raw((in.Timestamp).MarshalJSON()) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v DurationMetricReadable) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface10(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v DurationMetricReadable) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface10(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *DurationMetricReadable) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface10(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *DurationMetricReadable) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface10(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface11(in *jlexer.Lexer, out *CounterMetric) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "request_sum_per_minute": + out.RequestsSum = uint64(in.Uint64()) + case "requests_per_minute": + if in.IsNull() { + in.Skip() + } else { + in.Delim('{') + if !in.IsDelim('}') { + out.Requests = make(map[string]uint64) + } else { + out.Requests = nil + } + for !in.IsDelim('}') { + key := string(in.String()) + in.WantColon() + var v7 uint64 + v7 = uint64(in.Uint64()) + (out.Requests)[key] = v7 + in.WantComma() + } + in.Delim('}') + } + case "request_codes_per_minute": + if in.IsNull() { + in.Skip() + } else { + in.Delim('{') + if !in.IsDelim('}') { + out.RequestCodes = make(map[string]uint64) + } else { + out.RequestCodes = nil + } + for !in.IsDelim('}') { + key := string(in.String()) + in.WantColon() + var v8 uint64 + v8 = uint64(in.Uint64()) + (out.RequestCodes)[key] = v8 + in.WantComma() + } + in.Delim('}') + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface11(out *jwriter.Writer, in CounterMetric) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"request_sum_per_minute\":") + out.Uint64(uint64(in.RequestsSum)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"requests_per_minute\":") + if in.Requests == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { + out.RawString(`null`) + } else { + out.RawByte('{') + v9First := true + for v9Name, v9Value := range in.Requests { + if !v9First { + out.RawByte(',') + } + v9First = false + out.String(string(v9Name)) + out.RawByte(':') + out.Uint64(uint64(v9Value)) + } + out.RawByte('}') + } + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"request_codes_per_minute\":") + if in.RequestCodes == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { + out.RawString(`null`) + } else { + out.RawByte('{') + v10First := true + for v10Name, v10Value := range in.RequestCodes { + if !v10First { + out.RawByte(',') + } + v10First = false + out.String(string(v10Name)) + out.RawByte(':') + out.Uint64(uint64(v10Value)) + } + out.RawByte('}') + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CounterMetric) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface11(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CounterMetric) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface11(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CounterMetric) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface11(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CounterMetric) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface11(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface12(in *jlexer.Lexer, out *Tuple) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Path": + out.Path = string(in.String()) + case "Code": + out.Code = int(in.Int()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface12(out *jwriter.Writer, in Tuple) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"Path\":") + out.String(string(in.Path)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"Code\":") + out.Int(int(in.Code)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v Tuple) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface12(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v Tuple) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface12(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *Tuple) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface12(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *Tuple) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface12(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface13(in *jlexer.Lexer, out *KeyValuePair) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + out.Key = string(in.String()) + case "value": + out.Value = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface13(out *jwriter.Writer, in KeyValuePair) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"key\":") + out.String(string(in.Key)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"value\":") + out.String(string(in.Value)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v KeyValuePair) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface13(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v KeyValuePair) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface13(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *KeyValuePair) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface13(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *KeyValuePair) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface13(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface14(in *jlexer.Lexer, out *NameCodePair) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "name": + out.Name = string(in.String()) + case "code": + out.Code = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface14(out *jwriter.Writer, in NameCodePair) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"name\":") + out.String(string(in.Name)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"code\":") + out.String(string(in.Code)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v NameCodePair) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface14(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v NameCodePair) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface14(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *NameCodePair) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface14(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *NameCodePair) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface14(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface15(in *jlexer.Lexer, out *NewId) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "id": + out.Id = in.Interface() + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface15(out *jwriter.Writer, in NewId) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"id\":") + if m, ok := in.Id.(easyjson.Marshaler); ok { + m.MarshalEasyJSON(out) + } else if m, ok := in.Id.(json.Marshaler); ok { + out.Raw(m.MarshalJSON()) + } else { + out.Raw(json.Marshal(in.Id)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v NewId) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface15(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v NewId) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface15(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *NewId) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface15(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *NewId) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface15(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface16(in *jlexer.Lexer, out *WrappedResponse) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "message": + out.Message = string(in.String()) + case "content": + out.Content = in.Interface() + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface16(out *jwriter.Writer, in WrappedResponse) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"message\":") + out.String(string(in.Message)) + if in.Content != nil { + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"content\":") + if m, ok := in.Content.(easyjson.Marshaler); ok { + m.MarshalEasyJSON(out) + } else if m, ok := in.Content.(json.Marshaler); ok { + out.Raw(m.MarshalJSON()) + } else { + out.Raw(json.Marshal(in.Content)) + } + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v WrappedResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface16(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v WrappedResponse) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface16(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *WrappedResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface16(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *WrappedResponse) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface16(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface17(in *jlexer.Lexer, out *LoginResponse) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "message": + out.Message = string(in.String()) + case "redirectTo": + out.RedirectTo = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface17(out *jwriter.Writer, in LoginResponse) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"message\":") + out.String(string(in.Message)) + if in.RedirectTo != "" { + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"redirectTo\":") + out.String(string(in.RedirectTo)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v LoginResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface17(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v LoginResponse) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface17(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *LoginResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface17(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *LoginResponse) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface17(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface18(in *jlexer.Lexer, out *Token) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "token": + out.Token = string(in.String()) + case "expire": + out.Expire = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface18(out *jwriter.Writer, in Token) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"token\":") + out.String(string(in.Token)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"expire\":") + out.String(string(in.Expire)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v Token) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface18(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v Token) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface18(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *Token) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface18(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *Token) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface18(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface19(in *jlexer.Lexer, out *ChangePassword) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "old_password": + out.OldPassword = string(in.String()) + case "password": + out.Password = string(in.String()) + case "password_confirm": + out.PasswordConfirm = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface19(out *jwriter.Writer, in ChangePassword) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"old_password\":") + out.String(string(in.OldPassword)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"password\":") + out.String(string(in.Password)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"password_confirm\":") + out.String(string(in.PasswordConfirm)) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v ChangePassword) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface19(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v ChangePassword) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface19(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *ChangePassword) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface19(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *ChangePassword) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface19(l, v) +} +func easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface20(in *jlexer.Lexer, out *Login) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "id": + out.Id = string(in.String()) + case "password": + out.Password = string(in.String()) + case "redirect_to": + out.RedirectTo = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface20(out *jwriter.Writer, in Login) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"id\":") + out.String(string(in.Id)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"password\":") + out.String(string(in.Password)) + if in.RedirectTo != "" { + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"redirect_to\":") + out.String(string(in.RedirectTo)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v Login) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface20(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v Login) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDfb66c62EncodeAmuzEsGogsInfraChangerHttpIface20(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *Login) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface20(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *Login) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDfb66c62DecodeAmuzEsGogsInfraChangerHttpIface20(l, v) +} diff --git a/http/init.go b/http/init.go new file mode 100644 index 0000000..ed96d1f --- /dev/null +++ b/http/init.go @@ -0,0 +1,116 @@ +package http + +import ( + "net/http" + "time" + + "amuz.es/gogs/infra/changer/http/middleware/logging" + "amuz.es/gogs/infra/changer/http/middleware/recovery" + "amuz.es/gogs/infra/changer/http/middleware/session" + "amuz.es/gogs/infra/changer/http/route" + "amuz.es/gogs/infra/changer/http/template" + "amuz.es/gogs/infra/changer/util" + "github.com/gin-gonic/gin" + errs "github.com/pkg/errors" + graceful "gopkg.in/tylerb/graceful.v1" +) + +var ( + logger = util.NewLogger("http") + server *graceful.Server +) + +func InitHttp( + bindAddress string, + prefix string, + accessLogConfig *util.LogConfig, + ldapConfig *util.LdapConfig, + sessionConfig *util.SessionConfig, + profile bool, + errorSignal chan error, closeSignal chan struct{}) { + gin.SetMode(gin.ReleaseMode) + engine := gin.New() + + session.InitRole() + + initMiddleware(engine, accessLogConfig,ldapConfig, sessionConfig) + + initRoutes(engine, prefix, profile) + server = &graceful.Server{ + Timeout: 10 * time.Second, + Server: &http.Server{ + Addr: bindAddress, + Handler: engine, + }, + TCPKeepAlive: 3 * time.Second, + NoSignalHandling: true, + LogFunc: logger.Debugf, + } + go bind(server, errorSignal, closeSignal) + logger.Info(bindAddress + " bound") +} + +func CloseHttp() { + logger.Info("HTTP closing..") + server.Stop(10 * time.Second) + logger.Info("HTTP closed") +} +func bind(server *graceful.Server, errorSignal chan error, closeSignal chan struct{}) { + if err := server.ListenAndServe(); err != nil { + errorSignal <- errs.Wrap(err, "failed to listen or serve http") + } else { + close(closeSignal) + } +} +func initRoutes(engine *gin.Engine, prefix string, profile bool) { + suburl := prefix + path := engine.Group(suburl) + + path.StaticFS("/static", route.Static("")) + + + if profile { + logger.Info("enable Pprof handler ") + path.GET("/debug/pprof/", IndexHandler()) + path.GET("/debug/pprof/heap", HeapHandler()) + path.GET("/debug/pprof/goroutine", GoroutineHandler()) + path.GET("/debug/pprof/block", BlockHandler()) + path.GET("/debug/pprof/threadcreate", ThreadCreateHandler()) + path.GET("/debug/pprof/cmdline", CmdlineHandler()) + path.GET("/debug/pprof/profile", ProfileHandler()) + path.GET("/debug/pprof/symbol", SymbolHandler()) + path.POST("/debug/pprof/symbol", SymbolHandler()) + path.GET("/debug/pprof/trace", TraceHandler()) + } + + path.GET("/favicon.ico", func(c *gin.Context) { + c.Redirect(http.StatusMovedPermanently, "/static/favicon/images/favicon.ico") + }) + + path.GET("/manifest.json", func(c *gin.Context) { + c.Redirect(http.StatusMovedPermanently, "/static/favicon/manifest.json") + }) + + path.GET("/browserconfig.xml", func(c *gin.Context) { + c.Redirect(http.StatusMovedPermanently, "/static/favicon/browserconfig.xml") + }) + + path.GET("/", route.Index) + path.GET("/change_password", route.ChangePasswordView) + path.POST("/change_password", route.ChangePassword) + path.GET("/login", route.LoginView) + path.POST("/login", route.Login) + path.GET("/logout", route.Logout) +} + +func initMiddleware(engine *gin.Engine, accessLogConfig *util.LogConfig,ldapConfig *util.LdapConfig, sessionConfig *util.SessionConfig) { + engine.Use(logging.AccessLog(accessLogConfig)) + engine.Use(recovery.RecoveryJSON()) + engine.Use(session.New(ldapConfig, sessionConfig)) + + engine.HTMLRender = template.DefaultRender() + + // not found handler + engine.NoRoute(recovery.RecoveryHttpHTMLError(http.StatusNotFound)) + engine.NoMethod(recovery.RecoveryHttpHTMLError(http.StatusMethodNotAllowed)) +} diff --git a/http/middleware/logging/middleware.go b/http/middleware/logging/middleware.go new file mode 100644 index 0000000..0cf935e --- /dev/null +++ b/http/middleware/logging/middleware.go @@ -0,0 +1,154 @@ +// middleware +package logging + +import ( + "bytes" + "io" + "net" + "net/http" + "strconv" + "time" + + "amuz.es/gogs/infra/changer/http/iface" + "amuz.es/gogs/infra/changer/util" + "github.com/gin-gonic/gin" +) + +const ( + dateFormat = "02/Jan/2006:15:04:05 -0700" +) + +var DurationAspect = iface.NewRequestDurationAggr() +var CounterAspect = iface.NewCounterMetric() + +type logItem struct { + host string + method string + uri string + proto string + referer string + userAgent string + requestedHost string + requestedPath string + status int + responseSize int + requestTime time.Time + duration time.Duration +} + +func AccessLog(config *util.LogConfig) gin.HandlerFunc { + _, logWriter := util.NewLogWriter(config) + DurationAspect.StartTimer(10 * time.Second) + CounterAspect.StartTimer(1 * time.Minute) + logChan := make(chan logItem) + + go sendLogging(logWriter, logChan) + return func(c *gin.Context) { + now := time.Now() + req := c.Request + + defer func() { + dur := time.Now().Sub(now) + + logItemData := logItem{ + status: c.Writer.Status(), + responseSize: c.Writer.Size(), + requestTime: now, + duration: dur, + } + + if req != nil { + logItemData.host = remoteHost(req) + logItemData.method = req.Method + logItemData.uri = req.RequestURI + logItemData.proto = req.Proto + logItemData.referer = req.Referer() + logItemData.userAgent = req.UserAgent() + logItemData.requestedHost = req.Host + logItemData.requestedPath = req.URL.Path + } else { + logItemData.host = "-" + logItemData.method = "" + logItemData.uri = "" + logItemData.proto = "" + logItemData.referer = "" + logItemData.userAgent = "" + logItemData.requestedHost = "" + logItemData.requestedPath = "" + + } + + logChan <- logItemData + }() + + c.Next() + } +} +func sendLogging(accesslog io.Writer, logChan chan logItem) { + for { + select { + case logItemData := <-logChan: + DurationAspect.Add(float64(logItemData.duration.Nanoseconds())) + CounterAspect.Inc <- iface.Tuple{ + Path: logItemData.requestedPath, + Code: logItemData.status, + } + // Logs an access event in Apache combined log format (with a minor customization with the duration). + + buf := bytes.NewBufferString("") + buf.WriteString(logItemData.host) + buf.WriteString(` - - [`) + buf.WriteString(logItemData.requestTime.Format(dateFormat)) + buf.WriteString(`] "`) + buf.WriteString(logItemData.method) + buf.WriteByte(' ') + buf.WriteString(logItemData.uri) + buf.WriteByte(' ') + buf.WriteString(logItemData.proto) + buf.WriteString(`" `) + buf.WriteString(strconv.Itoa(logItemData.status)) + buf.WriteByte(' ') + buf.WriteString(strconv.Itoa(logItemData.responseSize)) + buf.WriteString(` "`) + buf.WriteString(logItemData.referer) + buf.WriteString(`" "`) + buf.WriteString(logItemData.userAgent) + buf.WriteString(`" `) + buf.WriteString(strconv.FormatInt((logItemData.duration.Nanoseconds() / time.Millisecond.Nanoseconds()), 10)) + buf.WriteByte(' ') + buf.WriteString(logItemData.requestedHost) + buf.WriteByte('\n') + accesslog.Write(buf.Bytes()) + } + } +} + +// strip port from addresses with hostname, ipv4 or ipv6 +func stripPort(address string) string { + if h, _, err := net.SplitHostPort(address); err == nil { + return h + } + + return address +} + +// The remote address of the client. When the 'X-Forwarded-For' +// header is set, then it is used instead. +func remoteAddr(r *http.Request) string { + ff := r.Header.Get("X-Forwarded-For") + if ff != "" { + return ff + } + + return r.RemoteAddr +} + +func remoteHost(r *http.Request) string { + a := remoteAddr(r) + h := stripPort(a) + if h != "" { + return h + } + + return "-" +} diff --git a/http/middleware/recovery/middleware.go b/http/middleware/recovery/middleware.go new file mode 100644 index 0000000..5d0b72f --- /dev/null +++ b/http/middleware/recovery/middleware.go @@ -0,0 +1,203 @@ +package recovery + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "net/http/httputil" + "runtime" + "strings" + + "amuz.es/gogs/infra/changer/http/iface" + "amuz.es/gogs/infra/changer/util" + "github.com/Sirupsen/logrus" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" +) + +var ( + dunno = []byte("???") + centerDot = []byte("·") + dot = []byte(".") + slash = []byte("/") + logger = util.NewLogger("recovery") + color = "danger" + preText = "루이보스 API 오류 :bomb:" + title = "API 요청을 처리하는 중에 의도하지 않은 오류가 발행하였습니다." + footer = "확인해 주세요! :hugging_face:" +) + +func recoveryInternal(stack []byte, code int, req *http.Request, err *string) { + httprequest, _ := httputil.DumpRequest(req, false) + detailInfo := map[string]interface{}{ + "method": req.Method, + "statusCode": code, + "path": req.URL.Path, + "message": err, + "request": string(httprequest), + "stack": string(stack), + } + // message := slack.Payload{ + // Attachments: []slack.Attachment{ + // convertSlackMessage(code, err, &stack, req, &httprequest), + // }, + // } + // slack.Send(util.Config.Slack.Url, "", message) + logger.WithFields(logrus.Fields(detailInfo)).Error("[Recovery] panic recovered:\n") +} + +func recoveryError(code int, _ *gin.Context) *iface.WrappedResponse { + return &iface.WrappedResponse{ + Message: http.StatusText(code), + } +} + +func RecoveryHttpJSONError(code int) gin.HandlerFunc { + return func(c *gin.Context) { + info := recoveryError(code, c) + util.DumpJSON(c, code, info) + } +} + +func RecoveryHttpHTMLError(code int) gin.HandlerFunc { + return func(c *gin.Context) { + info := recoveryError(code, c) + c.HTML(code, "views/error.html", pongo2.Context{ + "code": code, + "message": info.Message, + }) + } +} + +func RecoveryJSON() gin.HandlerFunc { + return func(c *gin.Context) { + defer func() { + if err := recover(); err != nil { + code := http.StatusInternalServerError + stack := stack(5) + systemErrMessage := err.(error).Error() + go recoveryInternal(stack, code, c.Copy().Request, &systemErrMessage) + util.DumpJSON(c, code, &iface.WrappedResponse{ + Message: systemErrMessage, + }) + c.Abort() + } + }() + c.Next() + } +} + +func RecoveryHTML() gin.HandlerFunc { + return func(c *gin.Context) { + defer func() { + if err := recover(); err != nil { + code := http.StatusInternalServerError + systemErrMessage := err.(error).Error() + c.HTML(code, "views/error.html", pongo2.Context{ + "code": code, + "message": systemErrMessage, + }) + c.Abort() + } + }() + c.Next() + } +} + +// stack returns a nicely formated stack frame, skipping skip frames +func stack(skip int) []byte { + buf := new(bytes.Buffer) // the returned data + // As we loop, we open files and read them. These variables record the currently + // loaded file. + var lines [][]byte + var lastFile string + for i := skip; ; i++ { + // Skip the expected number of frames + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + if paths := strings.SplitN(file, "src/", 2); len(paths) == 1 { + // Print this much at least. If we can't find the source, it won't show. + fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) + } else if vendors := strings.SplitN(paths[1], "vendor/", 2); len(vendors) == 1 { + // Print this much at least. If we can't find the source, it won't show. + fmt.Fprintf(buf, "%s:%d (0x%x)\n", paths[1], line, pc) + } else { + // Print this much at least. If we can't find the source, it won't show. + fmt.Fprintf(buf, "%s:%d (0x%x)\n", vendors[1], line, pc) + } + if file != lastFile { + data, err := ioutil.ReadFile(file) + if err != nil { + continue + } + lines = bytes.Split(data, []byte{'\n'}) + lastFile = file + } + fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line)) + } + return buf.Bytes() +} + +// source returns a space-trimmed slice of the n'th line. +func source(lines [][]byte, n int) []byte { + n-- // in stack trace, lines are 1-indexed but our array is 0-indexed + if n < 0 || n >= len(lines) { + return dunno + } + return bytes.TrimSpace(lines[n]) + +} + +// function returns, if possible, the name of the function containing the PC. +func function(pc uintptr) []byte { + fn := runtime.FuncForPC(pc) + if fn == nil { + return dunno + } + name := []byte(fn.Name()) + // The name includes the path name to the package, which is unnecessary + // since the file name is already included. Plus, it has center dots. + // That is, we see + // runtime/debug.*T·ptrmethod + // and want + // *T.ptrmethod + // Also the package path might contains dot (e.g. code.google.com/...), + // so first eliminate the path prefix + if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 { + name = name[lastslash+1:] + } + if period := bytes.Index(name, dot); period >= 0 { + name = name[period+1:] + } + name = bytes.Replace(name, centerDot, dot, -1) + return name +} + +// func convertSlackMessage( +// code int, err *string, stack *[]byte, +// req *http.Request, httpdumpreq *[]byte) (attachment slack.Attachment) { +// errmsg := "N/A" +// if err != nil { +// errmsg = *err +// } +// return slack.Attachment{ +// Color: &color, +// PreText: &preText, +// Title: &title, +// Footer: &footer, +// Text: err, +// Fields: []*slack.Field{ +// {Title: "status", Value: fmt.Sprintf("%s(%d)", http.StatusText(code), code), Short: true}, +// {Title: "method", Value: req.Method, Short: true}, +// {Title: "path", Value: req.URL.Path, Short: true}, +// {Title: "phase", Value: util.Config.Phase, Short: true}, +// {Title: "version", Value: util.Config.Version(), Short: true}, +// {Title: "message", Value: errmsg, Short: true}, +// {Title: "request", Value: string(*httpdumpreq), Short: false}, +// {Title: "stack", Value: string(*stack), Short: false}, +// }, +// } +// } diff --git a/http/middleware/secure/middleware.go b/http/middleware/secure/middleware.go new file mode 100644 index 0000000..ac85c21 --- /dev/null +++ b/http/middleware/secure/middleware.go @@ -0,0 +1,179 @@ +package secure + +import ( + "fmt" + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +const ( + stsHeader = "Strict-Transport-Security" + stsSubdomainString = "; includeSubdomains" + frameOptionsHeader = "X-Frame-Options" + frameOptionsValue = "DENY" + contentTypeHeader = "X-Content-Type-Options" + contentTypeValue = "nosniff" + xssProtectionHeader = "X-XSS-Protection" + xssProtectionValue = "1; mode=block" + cspHeader = "Content-Security-Policy" +) + +func defaultBadHostHandler(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Bad Host", http.StatusInternalServerError) +} + +// Options is a struct for specifying configuration options for the secure.Secure middleware. +type Options struct { + // AllowedHosts is a list of fully qualified domain names that are allowed. Default is empty list, which allows any and all host names. + AllowedHosts []string + // If SSLRedirect is set to true, then only allow https requests. Default is false. + SSLRedirect bool + // If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301). + SSLTemporaryRedirect bool + // SSLHost is the host name that is used to redirect http requests to https. Default is "", which indicates to use the same host. + SSLHost string + // SSLProxyHeaders is set of header keys with associated values that would indicate a valid https request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map. + SSLProxyHeaders map[string]string + // STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header. + STSSeconds int64 + // If STSIncludeSubdomains is set to true, the `includeSubdomains` will be appended to the Strict-Transport-Security header. Default is false. + STSIncludeSubdomains bool + // If FrameDeny is set to true, adds the X-Frame-Options header with the value of `DENY`. Default is false. + FrameDeny bool + // CustomFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value. This overrides the FrameDeny option. + CustomFrameOptionsValue string + // If ContentTypeNosniff is true, adds the X-Content-Type-Options header with the value `nosniff`. Default is false. + ContentTypeNosniff bool + // If BrowserXssFilter is true, adds the X-XSS-Protection header with the value `1; mode=block`. Default is false. + BrowserXssFilter bool + // ContentSecurityPolicy allows the Content-Security-Policy header value to be set with a custom value. Default is "". + ContentSecurityPolicy string + // When developing, the AllowedHosts, SSL, and STS options can cause some unwanted effects. Usually testing happens on http, not https, and on localhost, not your production domain... so set this to true for dev environment. + // If you would like your development environment to mimic production with complete Host blocking, SSL redirects, and STS headers, leave this as false. Default if false. + IsDevelopment bool + + // Handlers for when an error occurs (ie bad host). + BadHostHandler http.Handler +} + +// Secure is a middleware that helps setup a few basic security features. A single secure.Options struct can be +// provided to configure which features should be enabled, and the ability to override a few of the default values. +type secure struct { + // Customize Secure with an Options struct. + opt Options +} + +// Constructs a new Secure instance with supplied options. +func New(options Options) *secure { + if options.BadHostHandler == nil { + options.BadHostHandler = http.HandlerFunc(defaultBadHostHandler) + } + + return &secure{ + opt: options, + } +} + +func (s *secure) process(w http.ResponseWriter, r *http.Request) error { + // Allowed hosts check. + if len(s.opt.AllowedHosts) > 0 && !s.opt.IsDevelopment { + isGoodHost := false + for _, allowedHost := range s.opt.AllowedHosts { + if strings.EqualFold(allowedHost, r.Host) { + isGoodHost = true + break + } + } + + if !isGoodHost { + s.opt.BadHostHandler.ServeHTTP(w, r) + return fmt.Errorf("Bad host name: %s", r.Host) + } + } + + // SSL check. + if s.opt.SSLRedirect && s.opt.IsDevelopment == false { + isSSL := false + if strings.EqualFold(r.URL.Scheme, "https") || r.TLS != nil { + isSSL = true + } else { + for k, v := range s.opt.SSLProxyHeaders { + if r.Header.Get(k) == v { + isSSL = true + break + } + } + } + + if isSSL == false { + url := r.URL + url.Scheme = "https" + url.Host = r.Host + + if len(s.opt.SSLHost) > 0 { + url.Host = s.opt.SSLHost + } + + status := http.StatusMovedPermanently + if s.opt.SSLTemporaryRedirect { + status = http.StatusTemporaryRedirect + } + + http.Redirect(w, r, url.String(), status) + return fmt.Errorf("Redirecting to HTTPS") + } + } + + // Strict Transport Security header. + if s.opt.STSSeconds != 0 && !s.opt.IsDevelopment { + stsSub := "" + if s.opt.STSIncludeSubdomains { + stsSub = stsSubdomainString + } + + w.Header().Add(stsHeader, fmt.Sprintf("max-age=%d%s", s.opt.STSSeconds, stsSub)) + } + + // Frame Options header. + if len(s.opt.CustomFrameOptionsValue) > 0 { + w.Header().Add(frameOptionsHeader, s.opt.CustomFrameOptionsValue) + } else if s.opt.FrameDeny { + w.Header().Add(frameOptionsHeader, frameOptionsValue) + } + + // Content Type Options header. + if s.opt.ContentTypeNosniff { + w.Header().Add(contentTypeHeader, contentTypeValue) + } + + // XSS Protection header. + if s.opt.BrowserXssFilter { + w.Header().Add(xssProtectionHeader, xssProtectionValue) + } + + // Content Security Policy header. + if len(s.opt.ContentSecurityPolicy) > 0 { + w.Header().Add(cspHeader, s.opt.ContentSecurityPolicy) + } + + return nil + +} + +func Secure(options Options) gin.HandlerFunc { + s := New(options) + + return func(c *gin.Context) { + err := s.process(c.Writer, c.Request) + if err != nil { + if c.Writer.Written() { + c.AbortWithStatus(c.Writer.Status()) + } else { + c.AbortWithError(http.StatusInternalServerError, err) + } + } + } + +} diff --git a/http/middleware/session/data.go b/http/middleware/session/data.go new file mode 100644 index 0000000..b416f12 --- /dev/null +++ b/http/middleware/session/data.go @@ -0,0 +1,60 @@ +package session + +import "bytes" + +type userDetail struct { + id string + name string + mail string + role Role +} +type UserDetail interface { + Id() string + Name() string + Mail() string + Role() Role + ToModelContext() map[string]interface{} +} + +func (detail *userDetail) Id() string { + return detail.id +} +func (detail *userDetail) Name() string { + return detail.name +} +func (detail *userDetail) Mail() string { + return detail.mail +} +func (detail *userDetail) Role() Role { + return detail.role +} + +func (detail *userDetail) ToModelContext()map[string]interface{} { + context:=make(map[string]interface{}) + context["user_id"] = detail.id + context["user_name"] = detail.name + context["user_mail"] = detail.mail + context["user_role"] = detail.role.Type().Name() + return context +} + +func (detail *userDetail) String() string { + var buffer bytes.Buffer + buffer.WriteString("UserData(") + if detail != nil { + buffer.WriteString("id:") + buffer.WriteString(detail.id) + buffer.WriteString("name:") + buffer.WriteString(detail.name) + buffer.WriteString("role:") + if detail.role != nil { + buffer.WriteString(detail.role.String()) + } else { + buffer.WriteString("nil") + } + } else { + buffer.WriteString("nil") + } + buffer.WriteString(")") + return buffer.String() +} diff --git a/http/middleware/session/middleware.go b/http/middleware/session/middleware.go new file mode 100644 index 0000000..2222e59 --- /dev/null +++ b/http/middleware/session/middleware.go @@ -0,0 +1,121 @@ +package session + +import ( + "amuz.es/gogs/infra/changer/enums" + "amuz.es/gogs/infra/changer/http/iface" + "amuz.es/gogs/infra/changer/util" + "amuz.es/gogs/infra/changer/util/crypt" + "amuz.es/gogs/infra/changer/util/ldap" + "github.com/gin-gonic/gin" + "github.com/kataras/go-errors" +) + +var ( + logger = util.NewLogger("session") + cookieName string + cookieCryptor crypt.AesCryptor + Authenticator ldap.LdapAuthenticator +) + +func New(ldapConfig *util.LdapConfig, sessionConfig *util.SessionConfig) gin.HandlerFunc { + Authenticator = ldap.NewLdapAuthenticator( + ldapConfig.Host, ldapConfig.Port, + ldapConfig.SecurityProtocol, ldapConfig.SkipVerify, + "", "", + ldapConfig.BaseDN, + ldapConfig.UserDN, + ldapConfig.AttributeUsername, + ldapConfig.AttributeName, + ldapConfig.AttributeSurname, + ldapConfig.AttributeMail, + ldapConfig.Filter, + ldapConfig.AdminFilter, + ) + cookieName = sessionConfig.CookieName + cookieCryptor = crypt.NewAesCryptor([]byte(sessionConfig.Key)) + + return func(c *gin.Context) { + var ( + err error + detail = &userDetail{ + role: &roleAnonymous, + } + ) + defer func() { + c.Set("UserDetail", detail) + // if err != nil { + // logger.Debug("failed to TokenAuthFunc ", err) + // } + c.Next() + }() + + var cookie string + if cookie, err = c.Cookie(cookieName); err != nil { + return + } + + + var decryptedData []byte + + if decryptedData, err = cookieCryptor.DecryptEncoded(cookie); err != nil { + return + } + + var userData iface.UserData + if err := util.LoadJSON(decryptedData, &userData); err != nil { + return + } + + switch userData.Role { + case enums.UserTypeUser: + detail.role = &roleUser + case enums.UserTypeAdmin: + detail.role = &roleAdmin + default: + } + detail.id = userData.Id + detail.mail = userData.Mail + detail.name = userData.Name + return + } +} + +func AttachSession(c *gin.Context, id, mail, name string, role enums.UserType) { + userdata := &iface.UserData{ + Id: id, + Name: name, + Mail: mail, + Role: role, + } + + var ( + err error + encodedData []byte + ) + if encodedData, err = util.DumpJSONData(userdata); err != nil { + logger.Error(err) + return + } + + var encryptedData string + + if encryptedData, err = cookieCryptor.EncryptEncoded(encodedData); err != nil { + logger.Error(err) + return + } + + + c.SetCookie(cookieName, encryptedData, 3600, "", "", false, true) +} +func RemoveSession(c *gin.Context) { + c.SetCookie(cookieName, "", -1, "", "", false, true) +} + +func ExtractUserDetail(c *gin.Context) (UserDetail) { + if detail, exist := c.Get("UserDetail"); !exist { + panic(errors.New("UserDetail not exist")) + } else { + return detail.(UserDetail) + } + +} \ No newline at end of file diff --git a/http/middleware/session/role.go b/http/middleware/session/role.go new file mode 100644 index 0000000..d2a8ec0 --- /dev/null +++ b/http/middleware/session/role.go @@ -0,0 +1,62 @@ +package session + +import ( + "amuz.es/gogs/infra/changer/enums" + "github.com/mikespook/gorbac" + errs "github.com/pkg/errors" + "fmt" +) + +type ApiPerm gorbac.Permission + +type role struct { + roleType enums.UserType + gorbac.StdRole +} + +type Role interface { + Permit(gorbac.Permission) bool + String() string + Type() enums.UserType +} + +func newRole(roleType enums.UserType) role { + return role{ + roleType, + *gorbac.NewStdRole(roleType.Name()), + } +} + +func (roleData *role) Type() enums.UserType { + return roleData.roleType +} + +func (roleData *role) String() string { + return fmt.Sprint( + "Role(", + "name:", roleData.roleType.Name(), + ",desc:", roleData.roleType.String(), + ")", + ) +} + +var ( + roleAnonymous = newRole(enums.UserTypeAnon) + roleUser = newRole(enums.UserTypeUser) + roleAdmin = newRole(enums.UserTypeAdmin) +) +var ( + PermChangePasswordPerm = gorbac.NewStdPermission("PERM_CHANGE_PASSWORD") +) + +func InitRole() { + //initAssignPermission(&roleAnonymous, PermActSessCreate) + initAssignPermission(&roleUser, PermChangePasswordPerm) + initAssignPermission(&roleAdmin, PermChangePasswordPerm) +} + +func initAssignPermission(assignee *role, perm gorbac.Permission) { + if err := assignee.Assign(perm); err != nil { + panic(errs.Wrapf(err, "failed to assign permission %s -> role %s", assignee.roleType.Name(), perm.ID())) + } +} diff --git a/http/profile.go b/http/profile.go new file mode 100644 index 0000000..51db07b --- /dev/null +++ b/http/profile.go @@ -0,0 +1,69 @@ +package http + +import ( + "net/http/pprof" + "github.com/gin-gonic/gin" +) + +// IndexHandler will pass the call from /debug/pprof to pprof +func IndexHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Index(ctx.Writer, ctx.Request) + } +} + +// HeapHandler will pass the call from /debug/pprof/heap to pprof +func HeapHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Handler("heap").ServeHTTP(ctx.Writer, ctx.Request) + } +} + +// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof +func GoroutineHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Handler("goroutine").ServeHTTP(ctx.Writer, ctx.Request) + } +} + +// BlockHandler will pass the call from /debug/pprof/block to pprof +func BlockHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Handler("block").ServeHTTP(ctx.Writer, ctx.Request) + } +} + +// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof +func ThreadCreateHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Handler("threadcreate").ServeHTTP(ctx.Writer, ctx.Request) + } +} + +// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof +func CmdlineHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Cmdline(ctx.Writer, ctx.Request) + } +} + +// ProfileHandler will pass the call from /debug/pprof/profile to pprof +func ProfileHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Profile(ctx.Writer, ctx.Request) + } +} + +// SymbolHandler will pass the call from /debug/pprof/symbol to pprof +func SymbolHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Symbol(ctx.Writer, ctx.Request) + } +} + +// TraceHandler will pass the call from /debug/pprof/trace to pprof +func TraceHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + pprof.Trace(ctx.Writer, ctx.Request) + } +} diff --git a/http/route/change_password.go b/http/route/change_password.go new file mode 100644 index 0000000..2908bba --- /dev/null +++ b/http/route/change_password.go @@ -0,0 +1,65 @@ +package route + +import ( + "net/http" + "strings" + + "amuz.es/gogs/infra/changer/http/iface" + "amuz.es/gogs/infra/changer/http/middleware/session" + "amuz.es/gogs/infra/changer/util" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" +) + +func ChangePassword(c *gin.Context) { + context := session.ExtractUserDetail(c) + simplePermissionMatcher(c, session.PermChangePasswordPerm, context) + var ( + code int + body = iface.WrappedResponse{} + ) + defer func() { + if err := recover(); err != nil { + panic(err) + } else { + util.DumpJSON(c, code, body) + } + }() + + var ( + request iface.ChangePassword + ) + code, body.Message = 406, "요청이 올바르지 않습니다." + + // unboxing + if err := util.BindJSON(c, &request); err != nil { + logger.Error(err) + return + } + + code, body.Message = 406, "새 암호가 일치하지 않습니다." + if strings.Compare(request.Password, request.PasswordConfirm) > 0 { + return + } + var ( + err error + ) + + code, body.Message = 403, "ID가 잘못되었거나 기존암호가 일치하지 않습니다." + + if session.Authenticator.ChangePassword(context.Id(), request.OldPassword, request.Password, false) != nil { + logger.Error(err) + return + } + code, body.Message = 200, "성공" + +} + +func ChangePasswordView(c *gin.Context) { + context := session.ExtractUserDetail(c) + simplePermissionMatcher(c, session.PermChangePasswordPerm, context) + + modelContext:=pongo2.Context{} + modelContext.Update(context.ToModelContext()) + c.HTML(http.StatusOK, "views/change_password.html", modelContext) +} diff --git a/http/route/index.go b/http/route/index.go new file mode 100644 index 0000000..60a4aef --- /dev/null +++ b/http/route/index.go @@ -0,0 +1,16 @@ +package route + +import ( + "net/http" + + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" + "amuz.es/gogs/infra/changer/http/middleware/session" +) + +func Index(c *gin.Context) { + userDetail:= session.ExtractUserDetail(c) + modelContext:=pongo2.Context{} + modelContext.Update(userDetail.ToModelContext()) + c.HTML(http.StatusOK, "views/index.html", modelContext) +} diff --git a/http/route/login.go b/http/route/login.go new file mode 100644 index 0000000..e6e3a9d --- /dev/null +++ b/http/route/login.go @@ -0,0 +1,82 @@ +package route + +import ( + "net/http" + "strings" + + "amuz.es/gogs/infra/changer/enums" + "amuz.es/gogs/infra/changer/http/iface" + "amuz.es/gogs/infra/changer/http/middleware/session" + "amuz.es/gogs/infra/changer/util" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" +) + +func Login(c *gin.Context) { + var ( + code int + body = iface.LoginResponse{} + ) + defer func() { + if err := recover(); err != nil { + panic(err) + } else { + util.DumpJSON(c, code, body) + } + }() + + var ( + request iface.Login + ) + code, body.Message = 406, "요청이 올바르지 않습니다." + + // unboxing + if err := util.BindJSON(c, &request); err != nil { + logger.Error(err) + return + } + if len(request.RedirectTo) == 0 || strings.Contains(request.RedirectTo, "login") { + request.RedirectTo = "./" + } + + code, body.Message = 403, "ID가 잘못되었거나 기존암호가 일치하지 않습니다." + + if session.Authenticator.AuthenticateUser(request.Id, request.Password, false) != nil { + return + } + + code, body.Message, body.RedirectTo = 200, "성공!", request.RedirectTo + + var mail, name string + if userInfo, err := session.Authenticator.GetInfo(request.Id); err != nil { + return + } else { + name = userInfo["username"].(string) + mail = userInfo["mail"].(string) + } + + var role enums.UserType = enums.UserTypeAnon + if fetchedRole, err := session.Authenticator.SearchPermission(request.Id); err != nil { + logger.Info(err) + return + } else { + role = fetchedRole + } + + session.AttachSession(c, request.Id, mail, name, role) + +} + +func Logout(c *gin.Context) { + session.RemoveSession(c) + c.Redirect(302, "./") +} + +func LoginView(c *gin.Context) { + context := session.ExtractUserDetail(c) + modelContext := pongo2.Context{} + modelContext.Update(context.ToModelContext()) + modelContext["redirectTo"] = c.Query("redirectTo") + + c.HTML(http.StatusOK, "views/login.html", modelContext) +} diff --git a/http/route/services.go b/http/route/services.go new file mode 100644 index 0000000..9c1e9eb --- /dev/null +++ b/http/route/services.go @@ -0,0 +1,41 @@ +package route + +import ( + "errors" + "net/http" + "net/url" + "strings" + + "amuz.es/gogs/infra/changer/enums" + "amuz.es/gogs/infra/changer/http/middleware/session" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" +) + +func simplePermissionMatcher(c *gin.Context, perm session.ApiPerm, userDetail session.UserDetail) { + if userDetail == nil || userDetail.Role() == nil { + panic(errors.New("ResNoAuthenticate")) + } + if role := userDetail.Role(); !role.Permit(perm) { + if role.Type() == enums.UserTypeAnon { + //로그인 이동 + var ( + prevUrl = *c.Request.URL + ) + if !strings.Contains(prevUrl.Path, "login") { + queries:=prevUrl.Query() + queries.Add("redirectTo", prevUrl.Path) + moveUrl := url.URL{Path: "./login",RawQuery:queries.Encode()} + c.Redirect(302, moveUrl.String()) + } + } else { + //res = iface.ResInsufficientPerm + //403 + + c.HTML(http.StatusForbidden, "views/error.html", pongo2.Context{ + "code": http.StatusForbidden, + "message": http.StatusText(http.StatusForbidden), + }) + } + } +} diff --git a/http/route/static.go b/http/route/static.go new file mode 100644 index 0000000..4c60517 --- /dev/null +++ b/http/route/static.go @@ -0,0 +1,37 @@ +package route + +import ( + "net/http" + "strings" + + "amuz.es/gogs/infra/changer/bind/static" + assetfs "github.com/elazarl/go-bindata-assetfs" + "amuz.es/gogs/infra/changer/util" +) +var logger = util.NewLogger("route") + +type binaryFileSystem struct { + fs http.FileSystem +} + +func (b *binaryFileSystem) Open(name string) (http.File, error) { + return b.fs.Open(name) +} + +func (b *binaryFileSystem) Exists(prefix string, filepath string) bool { + + if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) { + if _, err := b.fs.Open(p); err != nil { + return false + } + return true + } + return false +} + +func Static(root string) *binaryFileSystem { + fs := &assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, AssetInfo: static.AssetInfo, Prefix: root} + return &binaryFileSystem{ + fs, + } +} diff --git a/http/template/loader.go b/http/template/loader.go new file mode 100644 index 0000000..32fb316 --- /dev/null +++ b/http/template/loader.go @@ -0,0 +1,60 @@ +package template + +import ( + "bytes" + "fmt" + "io" + "path/filepath" + "regexp" + + "github.com/flosch/pongo2" +) + +const filePathNormalizerFormat = `^%s?(.*)%s?$` +const seperator = string(filepath.Separator) + +type memoryTemplateLoader struct { + loaderFunc func(path string) ([]byte, error) + pathNormalizer *regexp.Regexp + fallbackLoader *pongo2.TemplateLoader +} + +//NewMemoryTemplateLoader loads a bindata template loader +func NewMemoryTemplateLoader(loaderFunc func(path string) ([]byte, error)) pongo2.TemplateLoader { + quotedSeperator := regexp.QuoteMeta(seperator) + return &memoryTemplateLoader{ + loaderFunc: loaderFunc, + pathNormalizer: regexp.MustCompile(fmt.Sprintf(filePathNormalizerFormat, quotedSeperator, quotedSeperator)), + } +} + +//NewMemoryTemplateLoaderWithFallback loads a bindata template loader, but if the file is not found +//it will try to find it in the fallback loader with the same path +func NewMemoryTemplateLoaderWithFallback(loaderFunc func(path string) ([]byte, error), fallbackLoader pongo2.TemplateLoader) pongo2.TemplateLoader { + return &memoryTemplateLoader{loaderFunc: loaderFunc, fallbackLoader: &fallbackLoader} +} + +func (m memoryTemplateLoader) Abs(base, name string) string { + if filepath.IsAbs(name) || base == "" { + return m.pathNormalizer.FindStringSubmatch(filepath.Clean(name))[1] + } + + if name == "" { + return m.pathNormalizer.FindStringSubmatch(filepath.Clean(base))[1] + } + + return m.pathNormalizer.FindStringSubmatch(filepath.Clean(filepath.Join(filepath.Dir(base), name)))[0] +} + +func (m memoryTemplateLoader) Get(path string) (io.Reader, error) { + data, err := m.loaderFunc(path) + if err != nil { + if m.fallbackLoader != nil { + return (*m.fallbackLoader).Get(path) + } + + return nil, err + } + + return bytes.NewReader(data), nil +} diff --git a/http/template/renderer.go b/http/template/renderer.go new file mode 100644 index 0000000..d7efe0c --- /dev/null +++ b/http/template/renderer.go @@ -0,0 +1,59 @@ +package template + +import ( + "net/http" + + "amuz.es/gogs/infra/changer/bind/template" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin/render" +) + +// RenderOptions is used to configure the renderer. +type RenderOptions struct { + contentType string + templateSet *pongo2.TemplateSet +} + +// Pongo2Render is a custom Gin template renderer using Pongo2. +type Pongo2Render struct { + template *pongo2.Template + contentType *string + context pongo2.Context +} + +// Default creates a Pongo2Render instance with default options. +func DefaultRender() *RenderOptions { + return &RenderOptions{ + contentType: "text/html; charset=utf-8", + templateSet: pongo2.NewSet("templates", NewMemoryTemplateLoader(template.Asset)), + } +} + +// Instance should return a new Pongo2Render struct per request and prepare +// the template by either loading it from disk or using pongo2's cache. +func (p *RenderOptions) Instance(name string, data interface{}) render.Render { + template, err := p.templateSet.FromFile(name) + if err != nil { + panic(err) + } + return &Pongo2Render{ + template: template, + contentType: &p.contentType, + context: data.(pongo2.Context), + } +} + +// Render should render the template to the response. +func (p *Pongo2Render) Render(w http.ResponseWriter) error { + writeContentType(w, []string{*p.contentType}) + return p.template.ExecuteWriter(p.context, w) +} + +// writeContentType is also in the gin/render package but it has not been made +// pubic so is repeated here, maybe convince the author to make this public. +func writeContentType(w http.ResponseWriter, value []string) { + header := w.Header() + if val := header["Content-Type"]; len(val) == 0 { + header["Content-Type"] = value + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..20bb9e6 --- /dev/null +++ b/main.go @@ -0,0 +1,143 @@ +package main + +import ( + "os" + "os/signal" + "runtime" + "syscall" + "time" + + "amuz.es/gogs/infra/changer/http" + "amuz.es/gogs/infra/changer/util" + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + app = kingpin.New(util.Config.Name(), "Inhouse internal user mgnt server").Author("Sangbum Kim") + verbose = app.Flag("verbose", "Enable verbose mode.").Short('v').Bool() + profile = app.Flag("profile", "Enable pprof mode.").Short('p').Bool() + logDir = app.Flag("log-dir", "logstore directory.").Short('L').String() + configFile = app.Flag("config-file", "config file path").Default("settings.yml").HintOptions("FILENAME").Short('C').String() + logger = util.NewLogger("main") +) + +func systemStart(closeSignal chan struct{}, errorSignal chan error) { + defer func() { + if err := recover(); err != nil { + errorSignal <- err.(error) + } + }() + start := time.Now() + app.Version(util.Config.Version()) + if _, err := app.Parse(os.Args[1:]); err != nil { + panic(err) + } + setMaxProcs() + + if err := util.LoadConfig(*configFile); err != nil { + panic(err) + } + + util.InitLogger(*verbose, *logDir, &util.Config.Logging.Application) + showBanner(util.Config.Phase, util.Config.Version(), util.Config.BuildDate()) + // init subsystem + + http.InitHttp( + util.Config.Bind, + util.Config.Prefix, + &util.Config.Logging.Access, + &util.Config.Ldap, + &util.Config.Session, + *profile, errorSignal, closeSignal) + + logger.Info("bootstrapped application ", time.Since(start)) + util.NotifyDaemon(util.DaemonStarted) +} + +func systemReload() { + util.RotateLogger() +} + +func systemTeardown(exitCode int) { + logger.Info("closing application") + util.NotifyDaemon(util.DaemonStopping) + http.CloseHttp() + logger.Info("bye") + os.Exit(exitCode) +} + +func main() { + var ( + exitCode = 0 + exitSignal = make(chan os.Signal, 1) + closeSignal = make(chan struct{}, 1) + errorSignal = make(chan error, 10) + ) + systemStart(closeSignal, errorSignal) + defer systemTeardown(exitCode) + signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) + + for { + select { + case <-closeSignal: + logger.Info("Service request to close this application") + return + case sysSignal := <-exitSignal: + switch sysSignal { + case syscall.SIGHUP: + systemReload() + default: + logger.Info("SYSCALL! ", sysSignal.String()) + return + } + case err := <-errorSignal: + logger.Error("exception raised! ", err) + exitCode = -1 + return + } + } +} + +func setMaxProcs() { + // TODO(vmarmol): Consider limiting if we have a CPU mask in effect. + // Allow as many threads as we have cores unless the user specified a value. + var numProcs int + // if *maxProcs < 1 { + numProcs = runtime.NumCPU() + // } else { + // numProcs = *maxProcs + // } + runtime.GOMAXPROCS(numProcs) + + // Check if the setting was successful. + actualNumProcs := runtime.GOMAXPROCS(0) + if actualNumProcs != numProcs { + logger.Warn("Specified max procs of %v but using %v", numProcs, actualNumProcs) + } +} + +func showBanner(phase string, version string, buildDate string) { + if util.LoggerIsStd() { + logger.Info(` + { + { } + }_{ __{ + .-{ } }-. ` + util.Config.Name() + ` + ( } { ) version: ` + version + ` + ` + "|`-.._____..-'| buildDate: " + buildDate + ` + | ;--. phase: ` + phase + ` + | (__ \ + | | ) ) + | |/ / + | / / + | ( / + \ y' + ` + "`-.._____..-'") + } else { + logger. + WithField("version", version). + WithField("buildDate", buildDate). + WithField("phase", phase). + Info("##", util.Config.Name()) + } +} diff --git a/settings.yml b/settings.yml new file mode 100644 index 0000000..f91b4e6 --- /dev/null +++ b/settings.yml @@ -0,0 +1,32 @@ +phase: development +logging: + application: + filename: "application.log" + maxsizemb: 500 + maxbackup: 30 + maxday: 14 + access: + filename: "access.log" + maxsizemb: 500 + maxbackup: 30 + maxday: 14 +session: + key: "q6Sb843fnDK2QdvEDom6UCw9S355L3K" + cookiename: "cook_changer" + expireseconds: 3600 +ldap: + host: ldaptext.server_here + port: 389 + securityprotocol: 0 + skipverify: true + basedn: "dc=example,dc=com" + userdn: "uid=%s,ou=People,dc=example,dc=com" + attributeusername: uid + attributename: givenName + attributesurname: sn + attributemail: mail + attributepassword: userPassword + filter: "(&(objectClass=person)(uid=%s)(memberof=CN=NormalUser,OU=Group,DC=example,DC=com))" + adminfilter: "(memberof=CN=NormalUser,OU=Group,DC=example,DC=com)" +bind: "0.0.0.0:8082" +prefix: "/infra/" \ No newline at end of file diff --git a/util/config.go b/util/config.go new file mode 100644 index 0000000..c00b680 --- /dev/null +++ b/util/config.go @@ -0,0 +1,84 @@ +package util + +import ( + "io/ioutil" + + "gopkg.in/yaml.v2" +) + + +type LogConfig struct { + FileName string + MaxSizeMb int + MaxBackup int + MaxDay int +} + +type SessionConfig struct { + Key string + CookieName string + ExpireSeconds int +} +type LdapConfig struct { + Host string + Port int + SecurityProtocol int + SkipVerify bool + BaseDN string + UserDN string + AttributeUsername string + AttributeName string + AttributeSurname string + AttributeMail string + AttributePassword string + Filter string + AdminFilter string +} + +type config struct { + Phase string + Bind string + Prefix string + Ldap LdapConfig + Session SessionConfig + Logging struct { + Application LogConfig + Access LogConfig + } +} + +func (c config) Name() string { + return name +} + +func (c config) Version() string { + return version +} + +func (c config) BuildDate() string { + return buildDate +} + +const name = "Changer" + +var ( + buildDate string + version string + Config = config{} +) + +func LoadConfig(path string) error { + var ( + source []byte + err error + ) + if source, err = ioutil.ReadFile(path); err != nil { + return err + } + + if err = yaml.Unmarshal(source, &Config); err != nil { + return err + } + + return nil +} diff --git a/util/crypt/aes.go b/util/crypt/aes.go new file mode 100644 index 0000000..8b0491c --- /dev/null +++ b/util/crypt/aes.go @@ -0,0 +1,170 @@ +package crypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "fmt" + "io" + "strings" + + "github.com/pkg/errors" +) + +func NewAesCryptor(key []byte) AesCryptor { + return &aesCryptor{ + key, + 12, + } +} + +type AesCryptor interface { + Encrypt(plaintext []byte) (data, nonce []byte, err error) + Decrypt(encrypted, nonce []byte) (data []byte, err error) + + EncryptEncoded(plaintext []byte) (data string, err error) + DecryptEncoded(encrypted string) (data []byte, err error) +} +type aesCryptor struct { + key []byte + nonceLength int +} + +func (c *aesCryptor) Encrypt(plaintext []byte) (data []byte, nonce []byte, err error) { + defer func() { + if r := recover(); r != nil { + if rerr, ok := r.(error); !ok { + err = fmt.Errorf("pkg: %v", r) + } else { + err = rerr + } + } + }() + + var block cipher.Block + block, err = aes.NewCipher(c.key) + if err != nil { + return + } + + // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. + nonce = make([]byte, c.nonceLength) + if _, err = io.ReadFull(rand.Reader, nonce); err != nil { + return + } + var aesgcm cipher.AEAD + aesgcm, err = cipher.NewGCM(block) + if err != nil { + return + } + + data = aesgcm.Seal(nil, nonce, plaintext, nil) + return +} + +func (c *aesCryptor) Decrypt(encrypted []byte, nonce []byte) (data []byte, err error) { + defer func() { + if r := recover(); r != nil { + if rerr, ok := r.(error); !ok { + err = fmt.Errorf("pkg: %v", r) + } else { + err = rerr + } + } + }() + + var block cipher.Block + block, err = aes.NewCipher(c.key) + if err != nil { + return + } + + var aesgcm cipher.AEAD + aesgcm, err = cipher.NewGCM(block) + if err != nil { + return + } + + data, err = aesgcm.Open(nil, nonce, encrypted, nil) + return +} + +func (c *aesCryptor) EncryptEncoded(plaintext []byte) (data string, err error) { + defer func() { + if r := recover(); r != nil { + if rerr, ok := r.(error); !ok { + err = fmt.Errorf("pkg: %v", r) + } else { + err = rerr + } + } + }() + var ( + encrypted []byte + nonce []byte + ) + encrypted, nonce, err = c.Encrypt(plaintext) + if err != nil { + return + } + var buf bytes.Buffer + encoder := base64.NewEncoder(base64.URLEncoding, &buf) + if _, err = encoder.Write(encrypted); err != nil { + return + } + + if err = encoder.Close(); err != nil { + return + } + buf.WriteRune('$') + + if _, err = encoder.Write(nonce); err != nil { + return + } + + if err = encoder.Close(); err != nil { + return + } + data = buf.String() + return +} +func (c *aesCryptor) DecryptEncoded(encryptedText string) (data []byte, err error) { + + defer func() { + if r := recover(); r != nil { + if rerr, ok := r.(error); !ok { + err = fmt.Errorf("pkg: %v", r) + } else { + err = rerr + } + } + }() + splittedText := strings.SplitN(encryptedText, "$", 2) + + if len(splittedText) != 2 { + err = errors.New("invalid data ") + return + } + + var ( + encrypted []byte + nonce []byte + ) + + if encrypted, err = base64.URLEncoding.DecodeString(splittedText[0]); err != nil { + return + } + + if nonce, err = base64.URLEncoding.DecodeString(splittedText[1]); err != nil{ + return + } + + if len(nonce) != c.nonceLength { + err = errors.Errorf("nonce length not %d ,actual %d", c.nonceLength, len(nonce)) + return + } + data, err = c.Decrypt(encrypted, nonce) + return +} diff --git a/util/crypt/common.go b/util/crypt/common.go new file mode 100644 index 0000000..75d916a --- /dev/null +++ b/util/crypt/common.go @@ -0,0 +1,5 @@ +package crypt + +import "amuz.es/gogs/infra/changer/util" + +var logger = util.NewLogger("crypto") diff --git a/util/crypt/password.go b/util/crypt/password.go new file mode 100644 index 0000000..ef2201d --- /dev/null +++ b/util/crypt/password.go @@ -0,0 +1,71 @@ +package crypt + +import ( + "bytes" + "crypto/rand" + "crypto/sha512" + "encoding/base64" + "strconv" + + "golang.org/x/crypto/pbkdf2" +) + +/* +import hashlib +from base64 import urlsafe_b64encode as encode +from base64 import urlsafe_b64decode as decode + +def makeSecret(password): +salt = os.urandom(4) +h = hashlib.sha1(password) +h.update(salt) +return "{SSHA}" + encode(h.digest() + salt) + +def checkPassword(challenge_password, password): +challenge_bytes = decode(challenge_password[6:]) +digest = challenge_bytes[:20] +salt = challenge_bytes[20:] +hr = hashlib.sha1(password) +hr.update(salt) +return digest == hr.digest() +*/ + +var ( + iter = 20000 + saltLengthByte = 16 + hasher = sha512.New +) + +func MakeSaltedPassword(password string) (string, error) { + salt := make([]byte, saltLengthByte) + if _, err := rand.Read(salt); err != nil { + return "", err + } + + dk := pbkdf2.Key([]byte(password), salt, iter, sha512.Size, hasher) + + var buffer bytes.Buffer + + buffer.WriteString("{PBKDF2-SHA512}") + buffer.WriteString(strconv.FormatUint((uint64)(iter), 10)) + buffer.WriteRune('$') + + encoder := base64.NewEncoder(base64.RawStdEncoding, &buffer) + + if _, err := encoder.Write(salt); err != nil { + return "", err + } + if err := encoder.Close(); err != nil { + return "", err + } + buffer.WriteRune('$') + + if _, err := encoder.Write(dk); err != nil { + return "", err + } + + if err := encoder.Close(); err != nil { + return "", err + } + return buffer.String(), nil +} diff --git a/util/daemon.go b/util/daemon.go new file mode 100644 index 0000000..55a7311 --- /dev/null +++ b/util/daemon.go @@ -0,0 +1,16 @@ +package util + +import "github.com/coreos/go-systemd/daemon" + +type notifyType string + +const ( + DaemonStarted notifyType = "READY=1" + DaemonStopping notifyType = "STOPPING=1" +) + +var sockPath string + +func NotifyDaemon(status notifyType) { + daemon.SdNotify(false, string(status)) +} diff --git a/util/iface/bytes16.go b/util/iface/bytes16.go new file mode 100644 index 0000000..1752f69 --- /dev/null +++ b/util/iface/bytes16.go @@ -0,0 +1,93 @@ +package iface + +import ( + "bytes" + "database/sql/driver" + "encoding/hex" + "errors" + "fmt" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" +) + +type Bytes16 [16]byte + +func (b Bytes16) Marshal() ([]byte, error) { + return b[:], nil +} + +func (b Bytes16) MarshalTo(buf []byte) (n int, err error) { + copy(buf, b[:]) + return len(b), nil +} +func (b *Bytes16) Unmarshal(buf []byte) error { + if len(buf) != 16 { + return fmt.Errorf("invalid bytes16 (got %d bytes)", len(buf)) + } + copy(b[:], buf) + return nil +} + +func (b Bytes16) Compare(other Bytes16) int { + return bytes.Compare(b[:], other[:]) +} + +func (b Bytes16) Equal(other Bytes16) bool { + return b.Compare(other) == 0 +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes16(buf []byte) (b Bytes16, err error) { + if len(buf) != hex.EncodedLen(len(b)) { + err = fmt.Errorf("invalid bytes16 length: %d", len(buf)) + } + _, err = hex.Decode(b[:], buf) + return +} + +func (b Bytes16) MarshalEasyJSON(w *jwriter.Writer) { + w.String(hex.EncodeToString(b[:])) +} +func (b *Bytes16) UnmarshalEasyJSON(w *jlexer.Lexer) { + if parsed, err := ParseBytes16([]byte(w.String())); err == nil { + *b = parsed + } +} + +func (b *Bytes16) Size() int { + if b == nil { + return 0 + } + return 16 +} + +func (b *Bytes16) FromHexString(buf []byte) (error) { + hexBuf := make([]byte, hex.DecodedLen(len(buf))) + if _, err := hex.Decode(hexBuf, buf); err != nil { + return err + } else if err := b.Unmarshal(hexBuf); err != nil { + return err + } + return nil +} + +func (b Bytes16) ToHexString() (string) { + return hex.EncodeToString(b[:]) +} + +// Scan implements the Scanner interface. +func (b *Bytes16) Scan(src interface{}) error { + switch src.(type) { + case string: + b.FromHexString([]byte(src.(string))) + default: + return errors.New("Incompatible type for UUID") + } + return nil +} + +// Value implements the driver Valuer interface. +func (b Bytes16) Value() (driver.Value, error) { + return b.ToHexString(), nil +} diff --git a/util/iface/bytes32.go b/util/iface/bytes32.go new file mode 100644 index 0000000..952a19e --- /dev/null +++ b/util/iface/bytes32.go @@ -0,0 +1,94 @@ +package iface + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" + "database/sql/driver" + "errors" +) + +type Bytes32 [32]byte + +func (b Bytes32) Marshal() ([]byte, error) { + return b[:], nil +} + +func (b Bytes32) MarshalTo(buf []byte) (n int, err error) { + copy(buf, b[:]) + return len(b), nil +} +func (b *Bytes32) Unmarshal(buf []byte) error { + if len(buf) != 32 { + return fmt.Errorf("invalid bytes32 (got %d bytes)", len(buf)) + } + copy(b[:], buf) + return nil +} + +func (b Bytes32) Compare(other Bytes32) int { + return bytes.Compare(b[:], other[:]) +} + +func (b Bytes32) Equal(other Bytes32) bool { + return b.Compare(other) == 0 +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes32(buf []byte) (b Bytes32, err error) { + if len(buf) != hex.EncodedLen(len(b)) { + err = fmt.Errorf("invalid bytes32 length: %d", len(buf)) + } + _, err = hex.Decode(b[:], buf) + return +} + +func (b Bytes32) MarshalEasyJSON(w *jwriter.Writer) { + w.String(hex.EncodeToString(b[:])) +} +func (b *Bytes32) UnmarshalEasyJSON(w *jlexer.Lexer) { + if parsed, err := ParseBytes32([]byte(w.String())); err == nil { + *b = parsed + } +} + +func (b *Bytes32) Size() int { + if b == nil { + return 0 + } + return 32 +} + + +func (b *Bytes32) FromHexString(buf []byte) (error) { + hexBuf := make([]byte, hex.DecodedLen(len(buf))) + if _, err := hex.Decode(hexBuf, buf); err != nil { + return err + } else if err := b.Unmarshal(hexBuf); err != nil { + return err + } + return nil +} + +func (b Bytes32) ToHexString() (string) { + return hex.EncodeToString(b[:]) +} + +// Scan implements the Scanner interface. +func (b *Bytes32) Scan(src interface{}) error { + switch src.(type) { + case string: + b.FromHexString([]byte(src.(string))) + default: + return errors.New("Incompatible type for UUID") + } + return nil +} + +// Value implements the driver Valuer interface. +func (b Bytes32) Value() (driver.Value, error) { + return b.ToHexString(), nil +} diff --git a/util/iface/bytes64.go b/util/iface/bytes64.go new file mode 100644 index 0000000..922581c --- /dev/null +++ b/util/iface/bytes64.go @@ -0,0 +1,93 @@ +package iface + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" + "database/sql/driver" + "errors" +) + +type Bytes64 [64]byte + +func (b Bytes64) Marshal() ([]byte, error) { + return b[:], nil +} + +func (b Bytes64) MarshalTo(buf []byte) (n int, err error) { + copy(buf, b[:]) + return len(b), nil +} +func (b *Bytes64) Unmarshal(buf []byte) error { + if len(buf) != 64 { + return fmt.Errorf("invalid bytes64 (got %d bytes)", len(buf)) + } + copy(b[:], buf) + return nil +} + +func (b Bytes64) Compare(other Bytes64) int { + return bytes.Compare(b[:], other[:]) +} + +func (b Bytes64) Equal(other Bytes64) bool { + return b.Compare(other) == 0 +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes64(buf []byte) (b Bytes64, err error) { + if len(buf) != hex.EncodedLen(len(b)) { + err = fmt.Errorf("invalid bytes64 length: %d", len(buf)) + } + _, err = hex.Decode(b[:], buf) + return +} + +func (b Bytes64) MarshalEasyJSON(w *jwriter.Writer) { + w.String(hex.EncodeToString(b[:])) +} +func (b *Bytes64) UnmarshalEasyJSON(w *jlexer.Lexer) { + if parsed, err := ParseBytes64([]byte(w.String())); err == nil { + *b = parsed + } +} +func (b *Bytes64) Size() int { + if b == nil { + return 0 + } + return 64 +} + + +func (b *Bytes64) FromHexString(buf []byte) (error) { + hexBuf := make([]byte, hex.DecodedLen(len(buf))) + if _, err := hex.Decode(hexBuf, buf); err != nil { + return err + } else if err := b.Unmarshal(hexBuf); err != nil { + return err + } + return nil +} + +func (b Bytes64) ToHexString() (string) { + return hex.EncodeToString(b[:]) +} + +// Scan implements the Scanner interface. +func (b *Bytes64) Scan(src interface{}) error { + switch src.(type) { + case string: + b.FromHexString([]byte(src.(string))) + default: + return errors.New("Incompatible type for UUID") + } + return nil +} + +// Value implements the driver Valuer interface. +func (b Bytes64) Value() (driver.Value, error) { + return b.ToHexString(), nil +} diff --git a/util/iface/serialize.go b/util/iface/serialize.go new file mode 100644 index 0000000..a4d8719 --- /dev/null +++ b/util/iface/serialize.go @@ -0,0 +1,22 @@ +package iface + +import ( + "github.com/mailru/easyjson/jwriter" + "github.com/mailru/easyjson/jlexer" + "amuz.es/gogs/infra/changer/util" +) + +var logger = util.NewLogger("common_iface") + +type Serializable interface { + Marshal() ([]byte, error) + Unmarshal(buf []byte) error + String() string +} + + + +type JSONSerializable interface { + MarshalEasyJSON(w *jwriter.Writer) + UnmarshalEasyJSON(w *jlexer.Lexer) +} \ No newline at end of file diff --git a/util/iface/uuid.go b/util/iface/uuid.go new file mode 100644 index 0000000..3856b68 --- /dev/null +++ b/util/iface/uuid.go @@ -0,0 +1,102 @@ +package iface + +import ( + "bytes" + "database/sql/driver" + "encoding/hex" + "errors" + "github.com/google/uuid" + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" +) + +type UUID struct { + uuid.UUID +} + +func (u UUID) Marshal() ([]byte, error) { + return u.MarshalBinary() +} + +func (u UUID) MarshalTo(buf []byte) (n int, err error) { + if len(u.UUID) == 0 { + return 0, nil + } + copy(buf, u.UUID[:]) + return len(u.UUID), nil +} +func (u *UUID) Unmarshal(buf []byte) error { + return u.UnmarshalBinary(buf) +} + +func (u UUID) Compare(other UUID) int { + return bytes.Compare(u.UUID[:], other.UUID[:]) +} + +func (u UUID) Equal(other UUID) bool { + return u.Compare(other) == 0 +} + +func (u UUID) MarshalEasyJSON(w *jwriter.Writer) { + w.String(hex.EncodeToString(u.UUID[:])) +} +func (u *UUID) UnmarshalEasyJSON(w *jlexer.Lexer) { + if decoded, err := hex.DecodeString(w.String()); err != nil { + return + } else if err := u.UnmarshalBinary(decoded); err != nil { + return + } +} + +func (u *UUID) Size() int { + if u == nil { + return 0 + } + if len((*u).UUID) == 0 { + return 0 + } + return 16 +} + +func NewUUIDV4() (u UUID, err error) { + var ui uuid.UUID + if ui, err = uuid.NewRandom(); err == nil { + u.UUID = ui + } + return +} + +func (u *UUID) UUIDFromHexString(buf []byte) (error) { + hexBuf := make([]byte, hex.DecodedLen(len(buf))) + if _, err := hex.Decode(hexBuf, buf); err != nil { + return err + } else if err := u.UnmarshalBinary(hexBuf); err != nil { + return err + } + return nil +} + +func (u UUID) ToHexString() (string) { + return hex.EncodeToString(u.UUID[:]) +} + +// Scan implements the Scanner interface. +func (u *UUID) Scan(src interface{}) error { + switch src.(type) { + case string: + u.UUIDFromHexString([]byte(src.(string))) + default: + return errors.New("Incompatible type for UUID") + } + return nil +} + +// Value implements the driver Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.ToHexString(), nil +} + +// Value implements the driver Valuer interface. +func (u UUID) Random() { + u.UUID = uuid.New() +} diff --git a/util/json.go b/util/json.go new file mode 100644 index 0000000..0077ce3 --- /dev/null +++ b/util/json.go @@ -0,0 +1,92 @@ +package util + +import ( + "bytes" + "encoding/json" + "errors" + "io" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" +) + +var jsonContentType = []string{"application/json; charset=utf-8"} + +func writeContentType(w http.ResponseWriter, value []string) { + header := w.Header() + if val := header["Content-Type"]; len(val) == 0 { + header["Content-Type"] = value + } +} + +func DumpJSONHeaderOnly(c *gin.Context, code int) { + c.Status(code) + + // Encode + header := c.Writer.Header() + if val := header["Content-Type"]; len(val) == 0 { + header["Content-Type"] = jsonContentType + } +} + +func DumpJSON(c *gin.Context, code int, serializable interface{}) { + c.Status(code) + + // Encode + header := c.Writer.Header() + if val := header["Content-Type"]; len(val) == 0 { + header["Content-Type"] = jsonContentType + } + + if enc := json.NewEncoder(c.Writer); enc == nil { + panic(errors.New("empty json encoder")) + } else if err := enc.Encode(serializable); err != nil { + panic(err) + } +} + +func DumpJSONData(serializable interface{}) (data []byte,err error){ + var buf bytes.Buffer + if enc := json.NewEncoder(&buf); enc == nil { + return nil,errors.New("empty json encoder") + } else if err := enc.Encode(serializable); err != nil { + return nil,err + }else{ + return buf.Bytes(),nil + } +} + +func LoadJSON(data []byte, deserializable interface{}) (err error) { + if reader := bytes.NewReader(data); reader == nil { + err = errors.New("empty json data") + } else { + err = LoadJSONReader(reader, deserializable) + } + return + +} + +func LoadJSONReader(r io.Reader, deserializable interface{}) (err error) { + decoder := json.NewDecoder(r) + + return decoder.Decode(deserializable) +} + +func BindJSON(c *gin.Context, deserializable interface{}) (err error) { + defer func() { + if err != nil { + c.AbortWithError(400, err).SetType(gin.ErrorTypeBind) + } + }() + if err = LoadJSONReader(c.Request.Body, deserializable); err != nil { + return + } + + // validate(obj) + + if binding.Validator == nil { + return nil + } + return binding.Validator.ValidateStruct(deserializable) +} diff --git a/util/ldap/ldap.go b/util/ldap/ldap.go new file mode 100644 index 0000000..44914e3 --- /dev/null +++ b/util/ldap/ldap.go @@ -0,0 +1,410 @@ +package ldap + +import ( + "fmt" + "strings" + + "amuz.es/gogs/infra/changer/enums" + "amuz.es/gogs/infra/changer/util" + "crypto/tls" + "github.com/pkg/errors" + "gopkg.in/ldap.v2" +) + +type SecurityProtocol int + +// Note: new type must be added at the end of list to maintain compatibility. +const ( + SECURITY_PROTOCOL_UNENCRYPTED SecurityProtocol = iota + SECURITY_PROTOCOL_LDAPS + SECURITY_PROTOCOL_START_TLS +) + +var logger = util.NewLogger("ldap") + +// Basic LDAP authentication service +type ldapHandler struct { + Host string // LDAP host + Port int // port number + SecurityProtocol SecurityProtocol + SkipVerify bool + BindDN string // DN to bind with + BindPassword string // Bind DN password + BaseDN string // Base search path for users + UserDN string // Template for the DN of the user for simple auth + AttributeUsername string // Username attribute + AttributeName string // First name attribute + AttributeSurname string // Surname attribute + AttributeMail string // E-mail attribute + AttributesInBind bool // fetch attributes in bind context (not user) + Filter string // Query filter to validate entry + AdminFilter string // Query filter to check if user is admin +} + +type LdapAuthenticator interface { + GetInfo(userId string) (map[string]interface{}, error) + AuthenticateUser(name, passwd string, directBind bool) (error) + SearchPermission(userId string) (enums.UserType, error) + ChangePassword(name, passwd string, newPassword string, directBind bool) (error) +} + +func NewLdapAuthenticator( + host string, + port int, + securityProtocol int, + skipVerify bool, + bindDN string, + bindPassword string, + baseDN string, + userDN string, + attributeUsername string, + attributeName string, + attributeSurname string, + attributeMail string, + filter string, + adminFilter string) LdapAuthenticator { + return &ldapHandler{ + Host: host, + Port: port, + SecurityProtocol: SecurityProtocol(securityProtocol), + SkipVerify: skipVerify, + BindDN: bindDN, + BindPassword: bindPassword, + BaseDN: baseDN, + UserDN: userDN, + AttributeUsername: attributeUsername, + AttributeName: attributeName, + AttributeSurname: attributeSurname, + AttributeMail: attributeMail, + Filter: filter, + AdminFilter: adminFilter, + } +} + +func (ls *ldapHandler) sanitizedUserQuery(username string) (string, bool) { + // See http://tools.ietf.org/search/rfc4515 + badCharacters := "\x00()*\\" + if strings.ContainsAny(username, badCharacters) { + logger.Debugf("Username contains invalid query characters: %s", username) + return "", false + } + + return fmt.Sprintf(ls.Filter, ldap.EscapeFilter(username)), true +} + +func (ls *ldapHandler) sanitizedUserDN(username string) (string, bool) { + // See http://tools.ietf.org/search/rfc4514: "special characters" + badCharacters := "\x00()*\\,='\"#+;<>" + if strings.ContainsAny(username, badCharacters) || strings.HasPrefix(username, " ") || strings.HasSuffix(username, " ") { + logger.Debugf("Username contains invalid query characters: %s", username) + return "", false + } + + return fmt.Sprintf(ls.UserDN, ldap.EscapeFilter(username)), true +} + +func (ls *ldapHandler) findUserDN(l *ldap.Conn, name string) (string, bool) { + logger.Debugf("Search for LDAP user: %s", name) + if ls.BindDN != "" && ls.BindPassword != "" { + err := l.Bind(ls.BindDN, ls.BindPassword) + if err != nil { + logger.Debugf("Failed to bind as BindDN '%s': %v", ls.BindDN, err) + return "", false + } + logger.Debugf("Bound as BindDN: %s", ls.BindDN) + } else { + logger.Debugf("Proceeding with anonymous LDAP search") + } + + // A search for the user. + userFilter, ok := ls.sanitizedUserQuery(name) + if !ok { + return "", false + } + + logger.Debugf("Searching for DN using filter '%s' and base '%s'", userFilter, ls.BaseDN) + search := ldap.NewSearchRequest( + ls.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, + false, userFilter, []string{}, nil) + + // Ensure we found a user + sr, err := l.Search(search) + if err != nil || len(sr.Entries) < 1 { + logger.Debugf("Failed search using filter '%s': %v", userFilter, err) + return "", false + } else if len(sr.Entries) > 1 { + logger.Debugf("Filter '%s' returned more than one user", userFilter) + return "", false + } + + userDN := sr.Entries[0].DN + if userDN == "" { + logger.Error(4, "LDAP search was successful, but found no DN!") + return "", false + } + + return userDN, true +} + +func dial(ls *ldapHandler) (*ldap.Conn, error) { + logger.Debugf("Dialing LDAP with security protocol '%v' without verifying: %v", ls.SecurityProtocol, ls.SkipVerify) + + tlsCfg := &tls.Config{ + ServerName: ls.Host, + InsecureSkipVerify: ls.SkipVerify, + } + if ls.SecurityProtocol == SECURITY_PROTOCOL_LDAPS { + return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), tlsCfg) + } + + conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port)) + if err != nil { + return nil, fmt.Errorf("Dial: %v", err) + } + + if ls.SecurityProtocol == SECURITY_PROTOCOL_START_TLS { + if err = conn.StartTLS(tlsCfg); err != nil { + conn.Close() + return nil, fmt.Errorf("StartTLS: %v", err) + } + } + + return conn, nil +} + +func bindUser(l *ldap.Conn, userDN, passwd string) error { + logger.Debugf("Binding with userDN: %s", userDN) + err := l.Bind(userDN, passwd) + if err != nil { + logger.Debugf("LDAP authentication failed for '%s': %v", userDN, err) + return err + } + logger.Debugf("Bound successfully with userDN: %s", userDN) + return err +} + +func changePassword(l *ldap.Conn, userDN, oldPasswd, newPasswd string) error { + logger.Debugf("Change Password userDN: %s", userDN) + + passwordModifyRequest := ldap.NewPasswordModifyRequest(userDN, oldPasswd, newPasswd) + + if _, err := l.PasswordModify(passwordModifyRequest); err != nil { + logger.Debugf("LDAP authentication failed for '%s': %v", userDN, err) + return err + } + + logger.Debugf("Change Password successfully with userDN: %s", userDN) + return nil +} + +// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter +func (ls *ldapHandler) SearchPermission(userId string) (enums.UserType, error) { + // See https://tools.ietf.org/search/rfc4513#section-5.1.2 + l, err := dial(ls) + if err != nil { + logger.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + return enums.UserTypeAnon, errors.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + } + defer l.Close() + + var userDN string + logger.Debugf("LDAP will use BindDN") + + var found bool + userDN, found = ls.findUserDN(l, userId) + if !found { + return enums.UserTypeAnon, errors.Errorf("cannot find user %s", userId) + } + + userType := enums.UserTypeUser + if len(ls.AdminFilter) > 0 { + logger.Debugf("Checking admin with filter '%s' and base '%s'", ls.AdminFilter, userDN) + search := ldap.NewSearchRequest( + userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, ls.AdminFilter, + []string{ls.AttributeName}, + nil) + + sr, err := l.Search(search) + if err != nil { + logger.Errorf("LDAP admin search failed: %v", err) + } else if len(sr.Entries) < 1 { + logger.Error("LDAP admin search failed: 0 entries") + } else { + userType = enums.UserTypeAdmin + } + } + return userType, nil +} + +// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter +func (ls *ldapHandler) GetInfo(userId string) (map[string]interface{}, error) { + // See https://tools.ietf.org/search/rfc4513#section-5.1.2 + result := make(map[string]interface{}) + result["role"] = enums.UserTypeAnon + + l, err := dial(ls) + if err != nil { + logger.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + return result, errors.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + } + defer l.Close() + + var userDN string + logger.Debugf("LDAP will use BindDN") + + var found bool + userDN, found = ls.findUserDN(l, userId) + if !found { + return result, errors.Errorf("cannot find user %s", userId) + } + + userFilter, ok := ls.sanitizedUserQuery(userId) + if !ok { + return result, errors.Errorf("cannot evulate user(%s) query", userId) + } + + logger.Debugf("Fetching attributes '%v', '%v', '%v', '%v' with filter '%s' and base '%s'", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN) + search := ldap.NewSearchRequest( + userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter, + []string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail}, + nil) + + sr, err := l.Search(search) + if err != nil { + logger.Errorf("LDAP search failed: %v", err) + return result, errors.Errorf("LDAP search failed: %v", err) + } else if len(sr.Entries) < 1 { + logger.Error("LDAP search failed: 0 entries") + return result, errors.New("LDAP search failed: 0 entries") + } + + result["username"] = sr.Entries[0].GetAttributeValue(ls.AttributeUsername) + result["firstName"] = sr.Entries[0].GetAttributeValue(ls.AttributeName) + result["surName"] = sr.Entries[0].GetAttributeValue(ls.AttributeSurname) + result["mail"] = sr.Entries[0].GetAttributeValue(ls.AttributeMail) + + userType := enums.UserTypeUser + if len(ls.AdminFilter) > 0 { + logger.Debugf("Checking admin with filter '%s' and base '%s'", ls.AdminFilter, userDN) + search := ldap.NewSearchRequest( + userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, ls.AdminFilter, + []string{ls.AttributeName}, + nil) + + sr, err := l.Search(search) + if err != nil { + logger.Errorf("LDAP admin search failed: %v", err) + } else if len(sr.Entries) < 1 { + logger.Error("LDAP admin search failed: 0 entries") + } else { + userType = enums.UserTypeAdmin + } + } + result["role"] = userType + + return result, nil +} + +// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter +func (ls *ldapHandler) AuthenticateUser(name, passwd string, directBind bool) (error) { + // See https://tools.ietf.org/search/rfc4513#section-5.1.2 + if len(passwd) == 0 { + logger.Debugf("authentication failed for '%s' with empty password", name) + return errors.Errorf("authentication failed for '%s' with empty password", name) + } + l, err := dial(ls) + if err != nil { + logger.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + return errors.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + } + defer l.Close() + + var userDN string + if directBind { + logger.Debugf("LDAP will bind directly via UserDN template: %s", ls.UserDN) + + var ok bool + userDN, ok = ls.sanitizedUserDN(name) + if !ok { + return errors.Errorf("cannot find user %s", name) + } + } else { + logger.Debugf("LDAP will use BindDN") + + var found bool + userDN, found = ls.findUserDN(l, name) + if !found { + return errors.Errorf("cannot find user %s", name) + } + } + + if directBind || !ls.AttributesInBind { + // binds user (checking password) before looking-up attributes in user context + err = bindUser(l, userDN, passwd) + if err != nil { + return errors.New("password not match") + } + } else { + // binds user (checking password) after looking-up attributes in BindDN context + err = bindUser(l, userDN, passwd) + if err != nil { + return errors.New("password not match") + } + } + return nil +} + +// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter +func (ls *ldapHandler) ChangePassword(name, passwd string, newPassword string, directBind bool) (error) { + // See https://tools.ietf.org/search/rfc4513#section-5.1.2 + if len(passwd) == 0 { + logger.Debugf("authentication failed for '%s' with empty password", name) + return errors.Errorf("authentication failed for '%s' with empty password", name) + } + l, err := dial(ls) + if err != nil { + logger.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + return errors.Errorf("LDAP connect failed for '%s': %v", ls.Host, err) + } + defer l.Close() + + var userDN string + if directBind { + logger.Debugf("LDAP will bind directly via UserDN template: %s", ls.UserDN) + + var ok bool + userDN, ok = ls.sanitizedUserDN(name) + if !ok { + return errors.Errorf("cannot find user %s", name) + } + } else { + logger.Debugf("LDAP will use BindDN") + + var found bool + userDN, found = ls.findUserDN(l, name) + if !found { + return errors.Errorf("cannot find user %s", name) + } + } + + if directBind || !ls.AttributesInBind { + // binds user (checking password) before looking-up attributes in user context + err = bindUser(l, userDN, passwd) + if err != nil { + return errors.New("password not match") + } + } else { + // binds user (checking password) after looking-up attributes in BindDN context + err = bindUser(l, userDN, passwd) + if err != nil { + return errors.New("password not match") + } + } + + err = changePassword(l, userDN, passwd, newPassword) + + if err != nil { + return errors.New("cannot change password") + } + return err +} diff --git a/util/logger.go b/util/logger.go new file mode 100644 index 0000000..adf0034 --- /dev/null +++ b/util/logger.go @@ -0,0 +1,73 @@ +package util + +import ( + "io" + "os" + "path" + + "github.com/Sirupsen/logrus" + prefixed "github.com/x-cray/logrus-prefixed-formatter" + lumberjack "gopkg.in/natefinch/lumberjack.v2" +) + +var ( + logger = logrus.StandardLogger() + rotaters []*lumberjack.Logger + logDir string + formatter = prefixed.TextFormatter{} +) + +func init() { + logger.Formatter = &formatter +} +func LoggerIsStd() bool { + return !formatter.DisableColors +} +func InitLogger(verbose bool, logDirArg string, config *LogConfig) { + logDir = logDirArg + colorSupport, writer := NewLogWriter(config) + formatter.DisableColors = !colorSupport + logger.Out = writer + if verbose { + logger.Level = logrus.DebugLevel + } else { + logger.Level = logrus.InfoLevel + } +} + +func NewLogger(prefix string) *logrus.Entry { + return logrus.NewEntry(logger).WithField("prefix", prefix) +} +func NewLogWriter(config *LogConfig) (bool, io.Writer) { + switch config.FileName { + case "Stdout": + return true, os.Stdout + case "Stderr": + return true, os.Stderr + default: + logpath := config.FileName + if logDir != "" { + logpath = path.Join(logDir, config.FileName) + } + logger.Info(" Attention!! log writes to ", config.FileName) + rotater := &lumberjack.Logger{ + Filename: logpath, + MaxSize: config.MaxSizeMb, // megabytes + MaxBackups: config.MaxBackup, + MaxAge: config.MaxDay, //days + } + rotaters = append(rotaters, rotater) + return false, rotater + } +} + +func RotateLogger() { + if len(rotaters) == 0 { + return + } + logger.Info("rotating logger") + for _, rotater := range rotaters { + rotater.Rotate() + } + logger.Info("rotated") +} diff --git a/util/parse.go b/util/parse.go new file mode 100644 index 0000000..10bc984 --- /dev/null +++ b/util/parse.go @@ -0,0 +1,138 @@ +package util + +import ( + "strconv" +) + +func mustParseInt(value string, bits int) int64 { + if parsed, err := strconv.ParseInt(value, 10, bits); err != nil { + panic(err) + } else { + return parsed + } +} + +func mustParseUint(value string, bits int) uint64 { + if parsed, err := strconv.ParseUint(value, 10, bits); err != nil { + panic(err) + } else { + return parsed + } +} + +func ParseUint8(value string) (ret *uint8) { + + if parsed, err := strconv.ParseUint(value, 10, 8); err == nil { + ret = new(uint8) + *ret = uint8(parsed) + } + return +} +func ParseUint16(value string) (ret *uint16) { + + if parsed, err := strconv.ParseUint(value, 10, 16); err == nil { + ret = new(uint16) + *ret = uint16(parsed) + } + return +} +func ParseUint32(value string) (ret *uint32) { + + if parsed, err := strconv.ParseUint(value, 10, 32); err == nil { + ret = new(uint32) + *ret = uint32(parsed) + } + return +} +func ParseUint64(value string) (ret *uint64) { + + if parsed, err := strconv.ParseUint(value, 10, 64); err == nil { + ret = new(uint64) + *ret = uint64(parsed) + } + return +} +func ParseUint(value string) (ret *uint) { + + if parsed, err := strconv.ParseUint(value, 10, 0); err == nil { + ret = new(uint) + *ret = uint(parsed) + } + return +} +func ParseInt8(value string) (ret *int8) { + + if parsed, err := strconv.ParseInt(value, 10, 8); err == nil { + ret = new(int8) + *ret = int8(parsed) + } + return +} +func ParseInt16(value string) (ret *int16) { + + if parsed, err := strconv.ParseInt(value, 10, 16); err == nil { + ret = new(int16) + *ret = int16(parsed) + } + return +} +func ParseInt32(value string) (ret *int32) { + + if parsed, err := strconv.ParseInt(value, 10, 32); err == nil { + ret = new(int32) + *ret = int32(parsed) + } + return +} +func ParseInt64(value string) (ret *int64) { + + if parsed, err := strconv.ParseInt(value, 10, 64); err == nil { + ret = new(int64) + *ret = int64(parsed) + } + return +} +func ParseInt(value string) (ret *int) { + if parsed, err := strconv.ParseInt(value, 10, 0); err == nil { + ret = new(int) + *ret = int(parsed) + } + return +} + +func ParseUint8Must(value string) uint8 { + return uint8(mustParseUint(value, 8)) +} +func ParseUint16Must(value string) uint16 { + return uint16(mustParseUint(value, 16)) +} +func ParseUint32Must(value string) uint32 { + return uint32(mustParseUint(value, 32)) +} +func ParseUint64Must(value string) uint64 { + return mustParseUint(value, 64) +} + +func ParseUintMust(value string) uint { + return uint(mustParseUint(value, 0)) +} + +func ParseInt8Must(value string) int8 { + return int8(mustParseInt(value, 8)) +} + +func ParseInt16Must(value string) int16 { + return int16(mustParseInt(value, 16)) +} + +func ParseInt32Must(value string) int32 { + return int32(mustParseInt(value, 32)) +} + +func ParseInt64Must(value string) int64 { + return mustParseInt(value, 64) +} + +func ParseIntMust(value string) int { + return int(mustParseInt(value, 0)) +} diff --git a/util/tool.go b/util/tool.go new file mode 100644 index 0000000..0d139e2 --- /dev/null +++ b/util/tool.go @@ -0,0 +1,313 @@ +package util + +import ( + "bytes" + "crypto/rand" + "fmt" + "image" + "math" + "reflect" + "strings" + "time" + "unsafe" +) + +func Int64ToBytes(s int64) []byte { + return []byte{ + byte(s >> 0), + byte(s >> 8), + byte(s >> 16), + byte(s >> 24), + byte(s >> 32), + byte(s >> 40), + byte(s >> 48), + byte(s >> 56), + } +} + +func BytesToInt64(s []byte) int64 { + return int64(0) | + (int64(s[0]) << 0) | + (int64(s[1]) << 8) | + (int64(s[2]) << 16) | + (int64(s[3]) << 24) | + (int64(s[4]) << 32) | + (int64(s[5]) << 40) | + (int64(s[6]) << 48) | + (int64(s[7]) << 56) +} + +func BytesToString(b []byte) string { + bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + sh := reflect.StringHeader{ + Data: bh.Data, + Len: bh.Len} + return *(*string)(unsafe.Pointer(&sh)) +} + +func StringToBytes(s string) []byte { + sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) + bh := reflect.SliceHeader{ + Data: sh.Data, + Len: sh.Len, + Cap: 0} + return *(*[]byte)(unsafe.Pointer(&bh)) +} + +// GetRandomString generate random string by specify chars. +func GetRandomString(n int, alphabets ...byte) string { + const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + var bytes = make([]byte, 0, n) + rand.Read(bytes) + for _, b := range bytes { + if len(alphabets) == 0 { + bytes = append(bytes, alphanum[b%byte(len(alphanum))]) + } else { + bytes = append(bytes, alphabets[b%byte(len(alphabets))]) + } + } + return string(bytes) +} + +// Seconds-based time units +var ( + NanoSecond uint64 = 1 + MicroSecond = 1000 * NanoSecond + MilliSecond = 1000 * MicroSecond + Second = 1000 * MilliSecond + Minute = 60 * Second + Hour = 60 * Minute + Day = 24 * Hour + Week = 7 * Day + Month = 30 * Day + Year = 12 * Month +) + +func computeTimeDiff(buff *bytes.Buffer, diff uint64) uint64 { + switch { + case diff < 1*NanoSecond: + diff = 0 + case diff < 2*NanoSecond: + diff = 0 + buff.WriteString("001ns") + case diff < 1*MicroSecond: + buff.WriteString(fmt.Sprintf("%03dns", diff)) + diff -= diff / NanoSecond * NanoSecond + case diff < 2*MicroSecond: + diff -= 1 * MilliSecond + buff.WriteString("001us") + case diff < 1*MilliSecond: + buff.WriteString(fmt.Sprintf("%03dus", diff/MicroSecond)) + diff -= diff / MicroSecond * MicroSecond + case diff < 2*MilliSecond: + diff -= 1 * Second + buff.WriteString("001ms") + case diff < 1*Second: + buff.WriteString(fmt.Sprintf("%03dms", diff/MilliSecond)) + diff -= diff / MilliSecond * MilliSecond + case diff < 2*Second: + diff -= 1 * Minute + buff.WriteString("01s") + case diff < 1*Minute: + buff.WriteString(fmt.Sprintf("%02ds", diff/Second)) + diff -= diff / Second * Second + case diff < 2*Minute: + diff -= 1 * Minute + buff.WriteString("01m") + case diff < 1*Hour: + buff.WriteString(fmt.Sprintf("%02dm", diff/Minute)) + diff -= diff / Minute * Minute + case diff < 2*Hour: + diff -= 1 * Hour + buff.WriteString("01h") + case diff < 1*Day: + buff.WriteString(fmt.Sprintf("%02dh", diff/Hour)) + diff -= diff / Hour * Hour + case diff < 2*Day: + diff -= 1 * Day + buff.WriteString("01d") + case diff < 1*Week: + buff.WriteString(fmt.Sprintf("%02dd", diff/Day)) + diff -= diff / Day * Day + case diff < 2*Week: + diff -= 1 * Week + buff.WriteString("1w") + case diff < 1*Month: + buff.WriteString(fmt.Sprintf("%01dw", diff/Week)) + diff -= diff / Week * Week + + case diff < 2*Month: + diff -= 1 * Month + buff.WriteString("01M") + case diff < 1*Year: + buff.WriteString(fmt.Sprintf("%02dM", diff/Month)) + diff -= diff / Month * Month + + case diff < 2*Year: + diff -= 1 * Year + buff.WriteString("01y") + default: + buff.WriteString(fmt.Sprintf("%02dy", diff/Year)) + diff = 0 + } + return diff +} + +// TimeSincePro calculates the time interval and generate full user-friendly string. +func TimeSincePro(then time.Time) string { + now := time.Now() + diff := uint64(now.UnixNano() - then.UnixNano()) + + if then.After(now) { + return "future" + } + + return TimeSinceDuration(diff) +} + +// TimeSincePro calculates the time interval and generate full user-friendly string. +func TimeSinceDuration(then uint64) string { + var ( + timeStr bytes.Buffer + diff = then + ) + + for { + diff = computeTimeDiff(&timeStr, diff) + if diff == 0 { + break + } else { + timeStr.WriteRune(' ') + } + } + if timeStr.Len() == 0 { + return "instant!" + + } else { + return timeStr.String() + } +} + +const ( + Byte = 1 + KByte = Byte * 1024 + MByte = KByte * 1024 + GByte = MByte * 1024 + TByte = GByte * 1024 + PByte = TByte * 1024 + EByte = PByte * 1024 +) + +var bytesSizeTable = map[string]uint64{ + "b": Byte, + "kb": KByte, + "mb": MByte, + "gb": GByte, + "tb": TByte, + "pb": PByte, + "eb": EByte, +} + +func logn(n, b float64) float64 { + return math.Log(n) / math.Log(b) +} + +func humanateBytes(s uint64, base float64, sizes []string) string { + if s < 10 { + return fmt.Sprintf("%dB", s) + } + e := math.Floor(logn(float64(s), base)) + suffix := sizes[int(e)] + val := float64(s) / math.Pow(base, math.Floor(e)) + f := "%.0f" + if val < 10 { + f = "%.1f" + } + + return fmt.Sprintf(f+"%s", val, suffix) +} + +// FileSize calculates the file size and generate user-friendly string. +func FileSize(s uint64) string { + sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} + return humanateBytes(s, 1024, sizes) +} + +// Subtract deals with subtraction of all types of number. +func Subtract(left interface{}, right interface{}) interface{} { + var rleft, rright int64 + var fleft, fright float64 + var isInt bool = true + switch left.(type) { + case int: + rleft = int64(left.(int)) + case int8: + rleft = int64(left.(int8)) + case int16: + rleft = int64(left.(int16)) + case int32: + rleft = int64(left.(int32)) + case int64: + rleft = left.(int64) + case float32: + fleft = float64(left.(float32)) + isInt = false + case float64: + fleft = left.(float64) + isInt = false + } + + switch right.(type) { + case int: + rright = int64(right.(int)) + case int8: + rright = int64(right.(int8)) + case int16: + rright = int64(right.(int16)) + case int32: + rright = int64(right.(int32)) + case int64: + rright = right.(int64) + case float32: + fright = float64(left.(float32)) + isInt = false + case float64: + fleft = left.(float64) + isInt = false + } + + if isInt { + return rleft - rright + } else { + return fleft + float64(rleft) - (fright + float64(rright)) + } +} + +// EllipsisString returns a truncated short string, +// it appends '...' in the end of the length of string is too large. +func EllipsisString(str string, length int) string { + if len(str) < length { + return str + } + return str[:length-3] + "..." +} + +func AspectRatio(srcRect image.Point, toResize uint64) image.Point { + w, h := int(toResize), getRatioSize(int(toResize), srcRect.Y, srcRect.X) + if srcRect.X < srcRect.Y { + w, h = getRatioSize(int(toResize), srcRect.X, srcRect.Y), int(toResize) + } + return image.Point{w, h} +} +func getRatioSize(a, b, c int) int { + d := a * b / c + return (d + 1) & -1 +} + +func Basename(s string) string { + n := strings.LastIndexByte(s, '.') + if n >= 0 { + return s[:n] + } + return s +}