├── .codeclimate.yml ├── .dev ├── scripts │ └── install-wp-tests.sh └── tests │ └── php │ ├── bootstrap.php │ └── test-simple-taxonomy-ordering.php ├── .distignore ├── .eslintrc.js ├── .github ├── CODEOWNERS └── workflows │ ├── eslint.yml │ ├── phpunit.yml │ ├── pre-release.yml │ ├── push-asset-readme-update.yml │ ├── push-deploy.yml │ ├── stylelint.yml │ ├── tagged-release.yml │ └── wpcs.yml ├── .gitignore ├── .stylelintignore ├── .stylelintrc.json ├── .svnignore ├── .wordpress-org ├── banner-772x250.jpg ├── icon-128x128.jpg ├── icon-256x256.jpg └── screenshot-1.jpg ├── Gruntfile.js ├── LICENSE ├── README.md ├── changelog.txt ├── composer.json ├── composer.lock ├── languages └── simple-taxonomy-ordering.pot ├── lib ├── css │ ├── select2.css │ ├── select2.min.css │ ├── yikes-tax-drag-drop.css │ └── yikes-tax-drag-drop.min.css ├── img │ └── sort-category-help-example.gif ├── js │ ├── select2.js │ ├── select2.min.js │ ├── yikes-tax-drag-drop.js │ └── yikes-tax-drag-drop.min.js └── options.php ├── package.json ├── phpcs.xml ├── phpunit.xml ├── readme.txt ├── uninstall.php ├── yarn.lock └── yikes-custom-taxonomy-order.php /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | plugins: 3 | duplication: 4 | enabled: false 5 | phpcodesniffer: 6 | enabled: true 7 | config: 8 | standard: "WordPress-Core" 9 | checks: 10 | file-lines: 11 | enabled: false 12 | method-count: 13 | enabled: false 14 | method-lines: 15 | enabled: false 16 | return-statements: 17 | enabled: false 18 | method-complexity: 19 | enabled: false 20 | exclude_patterns: 21 | - "**/select2*" 22 | - ".dev/tests/" 23 | - "Gruntfile.js" 24 | -------------------------------------------------------------------------------- /.dev/scripts/install-wp-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -lt 3 ]; then 4 | echo "usage: $0 [db-host] [wp-version]" 5 | exit 1 6 | fi 7 | 8 | DB_NAME=$1 9 | DB_USER=$2 10 | DB_PASS=$3 11 | DB_HOST=${4-localhost} 12 | WP_VERSION=${5-latest} 13 | 14 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} 15 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} 16 | 17 | download() { 18 | if [ `which curl` ]; then 19 | curl -s "$1" > "$2"; 20 | elif [ `which wget` ]; then 21 | wget -nv -O "$2" "$1" 22 | fi 23 | } 24 | 25 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then 26 | WP_TESTS_TAG="tags/$WP_VERSION" 27 | elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then 28 | WP_TESTS_TAG="trunk" 29 | else 30 | # http serves a single offer, whereas https serves multiple. we only want one 31 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json 32 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json 33 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') 34 | if [[ -z "$LATEST_VERSION" ]]; then 35 | echo "Latest WordPress version could not be found" 36 | exit 1 37 | fi 38 | WP_TESTS_TAG="tags/$LATEST_VERSION" 39 | fi 40 | 41 | set -ex 42 | 43 | install_wp() { 44 | 45 | if [ -d $WP_CORE_DIR ]; then 46 | return; 47 | fi 48 | 49 | mkdir -p $WP_CORE_DIR 50 | 51 | if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then 52 | mkdir -p /tmp/wordpress-nightly 53 | download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip 54 | unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/ 55 | mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR 56 | else 57 | if [ $WP_VERSION == 'latest' ]; then 58 | local ARCHIVE_NAME='latest' 59 | else 60 | local ARCHIVE_NAME="wordpress-$WP_VERSION" 61 | fi 62 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz 63 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR 64 | fi 65 | 66 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php 67 | } 68 | 69 | install_test_suite() { 70 | # portable in-place argument for both GNU sed and Mac OSX sed 71 | if [[ $(uname -s) == 'Darwin' ]]; then 72 | local ioption='-i .bak' 73 | else 74 | local ioption='-i' 75 | fi 76 | 77 | # set up testing suite if it doesn't yet exist 78 | if [ ! -d $WP_TESTS_DIR ]; then 79 | # set up testing suite 80 | mkdir -p $WP_TESTS_DIR 81 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes 82 | fi 83 | 84 | if [ ! -f wp-tests-config.php ]; then 85 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php 86 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php 87 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php 88 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php 89 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php 90 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php 91 | fi 92 | 93 | } 94 | 95 | install_db() { 96 | # parse DB_HOST for port or socket references 97 | local PARTS=(${DB_HOST//\:/ }) 98 | local DB_HOSTNAME=${PARTS[0]}; 99 | local DB_SOCK_OR_PORT=${PARTS[1]}; 100 | local EXTRA="" 101 | 102 | if ! [ -z $DB_HOSTNAME ] ; then 103 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then 104 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" 105 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then 106 | EXTRA=" --socket=$DB_SOCK_OR_PORT" 107 | elif ! [ -z $DB_HOSTNAME ] ; then 108 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" 109 | fi 110 | fi 111 | 112 | # create database 113 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA 114 | } 115 | 116 | install_wp 117 | install_test_suite 118 | install_db 119 | -------------------------------------------------------------------------------- /.dev/tests/php/bootstrap.php: -------------------------------------------------------------------------------- 1 | assertEquals( 31 | [ 32 | 'YIKES_STO_VERSION' => true, 33 | 'YIKES_STO_VERSION_CHECK' => '2.3.4', 34 | 'YIKES_STO_PATH' => true, 35 | 'YIKES_STO_URL' => true, 36 | 'YIKES_STO_NAME' => true, 37 | 'YIKES_STO_OPTION_NAME' => true, 38 | 'YIKES_STO_SELECT2_VERSION' => true, 39 | ], 40 | [ 41 | 'YIKES_STO_VERSION' => defined( 'YIKES_STO_VERSION' ), 42 | 'YIKES_STO_VERSION_CHECK' => YIKES_STO_VERSION, 43 | 'YIKES_STO_PATH' => defined( 'YIKES_STO_PATH' ), 44 | 'YIKES_STO_URL' => defined( 'YIKES_STO_URL' ), 45 | 'YIKES_STO_NAME' => defined( 'YIKES_STO_NAME' ), 46 | 'YIKES_STO_OPTION_NAME' => defined( 'YIKES_STO_OPTION_NAME' ), 47 | 'YIKES_STO_SELECT2_VERSION' => defined( 'YIKES_STO_SELECT2_VERSION' ), 48 | ] 49 | ); 50 | 51 | } 52 | 53 | /** 54 | * Test the Yikes_Custom_Taxonomy_Order class exists. 55 | * 56 | * @since 2.3.4 57 | */ 58 | function testClassExists() { 59 | 60 | $this->assertTrue( class_exists( 'Yikes_Custom_Taxonomy_Order' ) ); 61 | 62 | } 63 | 64 | /** 65 | * Test the YIKES_Simple_Taxonomy_Options class exists. 66 | * 67 | * @since 2.3.4 68 | */ 69 | function testIncludeFiles() { 70 | 71 | $this->assertTrue( class_exists( 'YIKES_Simple_Taxonomy_Options' ) ); 72 | 73 | } 74 | 75 | /** 76 | * Test that category taxonomy ordering works. 77 | * 78 | * This test will: 79 | * 1. Add three custom categories to the post categories. 80 | * 2. Check that get_terms() returns the categories in the default order. 1, 2, 3. 81 | * 3. Enable custom sorting for post categories. 82 | * 4. Update the custom categories to reverse order. 3, 2, 1. 83 | * 5. Check that get_terms() now returns the categories in our custom order. 3, 2, 1. 84 | * 85 | * @since 2.3.4 86 | */ 87 | function testCustomTaxonomyOrderWorks() { 88 | 89 | // Insert post categories 90 | $post_categories = [ 91 | 'custom_one' => [ 92 | 'name' => 'Custom Category 1', 93 | ], 94 | 'custom_two' => [ 95 | 'name' => 'Custom Category 2', 96 | ], 97 | 'custom_three' => [ 98 | 'name' => 'Custom Category 3', 99 | ], 100 | ]; 101 | 102 | // Insert custom post categories. 103 | foreach ( $post_categories as $category_slug => $category_data ) { 104 | 105 | wp_insert_term( 106 | $category_data['name'], 107 | 'category', 108 | array( 109 | 'slug' => $category_slug 110 | ) 111 | ); 112 | 113 | } 114 | 115 | $categories = get_terms( 116 | array( 117 | 'taxonomy' => 'category', 118 | 'hide_empty' => false, 119 | 'exclude' => array( 1 ), // Exclude uncategorized. 120 | ) 121 | ); 122 | 123 | $this->assertEquals( 124 | array( 125 | 'Custom Category 1', 126 | 'Custom Category 2', 127 | 'Custom Category 3', 128 | ), 129 | array( 130 | $categories[0]->name, 131 | $categories[1]->name, 132 | $categories[2]->name, 133 | ), 134 | 'The original order of the post categories is not correct.' 135 | ); 136 | 137 | // Enable sorting on categories. 138 | update_option( 'yikes_simple_taxonomy_ordering_options', array( 'enabled_taxonomies' => array( 'category' ) ) ); 139 | 140 | $index = 1; 141 | 142 | foreach ( array_reverse( $post_categories ) as $category_slug => $category_data ) { 143 | 144 | $term = get_term_by( 'slug', $category_slug, 'category' ); 145 | 146 | if ( ! is_a( $term, 'WP_Term' ) ) { 147 | 148 | continue; 149 | 150 | } 151 | 152 | update_term_meta( $term->term_id, 'tax_position', $index ); 153 | 154 | $index++; 155 | 156 | } 157 | 158 | $categories = get_terms( 159 | array( 160 | 'taxonomy' => 'category', 161 | 'hide_empty' => false, 162 | 'exclude' => array( 1 ), // Exclude uncategorized. 163 | ) 164 | ); 165 | 166 | $this->assertEquals( 167 | array( 168 | 'Custom Category 3', 169 | 'Custom Category 2', 170 | 'Custom Category 1', 171 | ), 172 | array( 173 | $categories[0]->name, 174 | $categories[1]->name, 175 | $categories[2]->name, 176 | ), 177 | 'The custom order of the post categories is not correct.' 178 | ); 179 | 180 | } 181 | 182 | /** 183 | * Test to see if a given taxonomy does not have sorting enabled. 184 | */ 185 | function testIsTaxonomySortingNotEnabled() { 186 | 187 | $this->assertFalse( ( new Yikes_Custom_Taxonomy_Order() )->is_taxonomy_ordering_enabled( 'non_existing_taxonomy_slug' ) ); 188 | 189 | } 190 | 191 | /** 192 | * Test to see if a given taxonomy has sorting enabled. 193 | */ 194 | function testIsTaxonomySortingEnabled() { 195 | 196 | update_option( 'yikes_simple_taxonomy_ordering_options', array( 'enabled_taxonomies' => array( 'category' ) ) ); 197 | 198 | $this->assertTrue( ( new Yikes_Custom_Taxonomy_Order() )->is_taxonomy_ordering_enabled( 'category' ) ); 199 | 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /.distignore: -------------------------------------------------------------------------------- 1 | # Directories 2 | /.wordpress-org 3 | /.git 4 | /.github 5 | /node_modules 6 | vendor/ 7 | build/ 8 | .dev/ 9 | 10 | # Files 11 | .distignore 12 | .gitignore 13 | .scrutinizer.yml 14 | .svnignore 15 | Gruntfile.js 16 | LICENSE 17 | README.md 18 | composer.json 19 | composer.lock 20 | package.json 21 | yarn.lock 22 | phpcs.xml 23 | phpunit.xml 24 | .husky 25 | .stylelintrc.json 26 | .stylelintignore 27 | .eslintrc.js 28 | .DS_Store 29 | .phpunit.result.cache 30 | .codeclimate.yml 31 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "eslint:recommended", 3 | "env": { 4 | "browser": true, 5 | "es2021": true 6 | }, 7 | "ignorePatterns": [ 8 | "lib/js/*.min.js", 9 | "lib/js/select2.js" 10 | ], 11 | "globals": { 12 | "lityScriptData": true, 13 | "jQuery": true 14 | }, 15 | "parserOptions": { 16 | "ecmaVersion": "latest" 17 | }, 18 | "rules": { 19 | "no-extra-boolean-cast": "off" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @EvanHerman 2 | -------------------------------------------------------------------------------- /.github/workflows/eslint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: ESLint 3 | 4 | on: push 5 | 6 | jobs: 7 | eslint: 8 | name: ESLint 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - uses: php-actions/composer@v5 15 | 16 | - name: Yarn Install 17 | run: yarn install 18 | 19 | - name: Run eslint 20 | run: yarn lint:js 21 | -------------------------------------------------------------------------------- /.github/workflows/phpunit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: PHPUnit Tests 3 | 4 | on: push 5 | 6 | jobs: 7 | phpunit: 8 | name: PHPUnit 9 | runs-on: ubuntu-latest 10 | 11 | services: 12 | mysql: 13 | image: mysql:latest 14 | env: 15 | MYSQL_HOST: 127.0.0.1 16 | MYSQL_ROOT_PASSWORD: password 17 | ports: 18 | - 3306:3306 19 | options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | 24 | - uses: php-actions/composer@v5 25 | 26 | - name: Setup PHP with Xdebug 27 | uses: shivammathur/setup-php@v2 28 | with: 29 | php-version: '8.1' 30 | coverage: xdebug 31 | 32 | - name: Install Tests 33 | run: yarn install:tests 34 | 35 | - name: Composer Install 36 | run: sudo composer install 37 | 38 | - name: Run unit tests 39 | run: yarn test:php-coverage-cli 40 | 41 | - name: Comment Unit Test Results on PR 42 | uses: EnricoMi/publish-unit-test-result-action@v1.39 43 | if: always() 44 | with: 45 | files: "junit.xml" 46 | 47 | - name: Publish Unit Test Results to Code Climate 48 | uses: aktions/codeclimate-test-reporter@v1 49 | with: 50 | codeclimate-test-reporter-id: ${{ secrets.CODE_CLIMATE_TEST_REPORTER_ID }} 51 | command: after-build --coverage-input-type clover 52 | -------------------------------------------------------------------------------- /.github/workflows/pre-release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Pre-Release 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | pre-release: 11 | name: Pre Release 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - uses: GuillaumeFalourd/setup-rsync@v1 18 | 19 | - name: Install yarn dependencies 20 | run: yarn install 21 | 22 | - name: Build the plugin 23 | run: | 24 | yarn min 25 | sudo mkdir -p ./build/simple-taxonomy-ordering 26 | sudo rsync -av --exclude-from .distignore --delete . build/simple-taxonomy-ordering/ 27 | cd ./build 28 | sudo zip -r simple-taxonomy-ordering.zip simple-taxonomy-ordering/. 29 | 30 | - uses: marvinpinto/action-automatic-releases@latest 31 | with: 32 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 33 | automatic_release_tag: latest 34 | prerelease: true 35 | title: Development Build 36 | files: ./build/simple-taxonomy-ordering.zip 37 | -------------------------------------------------------------------------------- /.github/workflows/push-asset-readme-update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Plugin asset/readme update 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | master: 11 | name: Push to master 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@master 15 | - name: WordPress.org plugin asset/readme update 16 | uses: 10up/action-wordpress-plugin-asset-update@stable 17 | env: 18 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} 19 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }} 20 | SLUG: simple-taxonomy-ordering 21 | -------------------------------------------------------------------------------- /.github/workflows/push-deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Deploy to WordPress.org 3 | 4 | on: 5 | push: 6 | tags: 7 | - '*' 8 | 9 | jobs: 10 | tag: 11 | name: Deploy to WordPress.org 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@master 15 | - name: WordPress Plugin Deploy 16 | uses: 10up/action-wordpress-plugin-deploy@stable 17 | env: 18 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} 19 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }} 20 | SLUG: simple-taxonomy-ordering 21 | -------------------------------------------------------------------------------- /.github/workflows/stylelint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Stylelint 3 | 4 | on: push 5 | 6 | jobs: 7 | stylelint: 8 | name: Stylelint 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - uses: php-actions/composer@v5 15 | 16 | - name: Yarn Install 17 | run: yarn install 18 | 19 | - name: Run stylelint 20 | run: yarn lint:css 21 | -------------------------------------------------------------------------------- /.github/workflows/tagged-release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tagged Release 3 | 4 | on: 5 | push: 6 | tags: 7 | - "v*" 8 | 9 | jobs: 10 | tagged-release: 11 | name: Tagged Release 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - uses: GuillaumeFalourd/setup-rsync@v1 18 | 19 | - name: Install yarn dependencies 20 | run: yarn install 21 | 22 | - name: Build the plugin 23 | run: | 24 | yarn min 25 | sudo mkdir -p ./build/simple-taxonomy-ordering 26 | sudo rsync -av --exclude-from .distignore --delete . ./build/simple-taxonomy-ordering/ 27 | cd ./build 28 | sudo zip -r simple-taxonomy-ordering.zip simple-taxonomy-ordering/. 29 | - uses: marvinpinto/action-automatic-releases@latest 30 | with: 31 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 32 | prerelease: false 33 | files: ./build/simple-taxonomy-ordering.zip 34 | -------------------------------------------------------------------------------- /.github/workflows/wpcs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: WPCS Check 3 | 4 | on: push 5 | 6 | jobs: 7 | wpcs: 8 | name: WPCS 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: WPCS check 13 | uses: 10up/wpcs-action@stable 14 | with: 15 | use_local_config: true 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | vendor/ 3 | build/ 4 | .dev/tests/php/coverage/ 5 | .husky 6 | .DS_Store 7 | .phpunit.result.cache 8 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | lib/css/*.min.css 2 | lib/css/select2.css 3 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard" 3 | } 4 | -------------------------------------------------------------------------------- /.svnignore: -------------------------------------------------------------------------------- 1 | Gruntfile.js 2 | package.json 3 | yarn.lock 4 | README.md 5 | .gitignore 6 | phpcs.xml 7 | .husky 8 | .stylelintrc.json 9 | .stylelintignore 10 | .eslintrc.js 11 | build/ 12 | .dev/ 13 | .DS_Store 14 | .phpunit.result.cache 15 | .codeclimate.yml 16 | -------------------------------------------------------------------------------- /.wordpress-org/banner-772x250.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvanHerman/simple-taxonomy-ordering/6ba5fabf0bd0f18f04b6b0088229e73286549db1/.wordpress-org/banner-772x250.jpg -------------------------------------------------------------------------------- /.wordpress-org/icon-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvanHerman/simple-taxonomy-ordering/6ba5fabf0bd0f18f04b6b0088229e73286549db1/.wordpress-org/icon-128x128.jpg -------------------------------------------------------------------------------- /.wordpress-org/icon-256x256.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvanHerman/simple-taxonomy-ordering/6ba5fabf0bd0f18f04b6b0088229e73286549db1/.wordpress-org/icon-256x256.jpg -------------------------------------------------------------------------------- /.wordpress-org/screenshot-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvanHerman/simple-taxonomy-ordering/6ba5fabf0bd0f18f04b6b0088229e73286549db1/.wordpress-org/screenshot-1.jpg -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function( grunt ) { 2 | 'use strict'; 3 | 4 | const pkg = grunt.file.readJSON( 'package.json' ); 5 | 6 | grunt.initConfig( { 7 | 8 | pkg, 9 | 10 | replace: { 11 | php: { 12 | src: [ 13 | 'yikes-custom-taxonomy-order.php', 14 | 'lib/**/*.php', 15 | ], 16 | overwrite: true, 17 | replacements: [ 18 | { 19 | from: /Version:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 20 | to: 'Version:$1' + pkg.version, 21 | }, 22 | { 23 | from: /@since(.*?)NEXT/mg, 24 | to: '@since$1' + pkg.version, 25 | }, 26 | { 27 | from: /Version:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 28 | to: 'Version:$1' + pkg.version, 29 | }, 30 | { 31 | from: /define\(\s*'YIKES_STO_VERSION',\s*'(.*)'\s*\);/, 32 | to: 'define( \'YIKES_STO_VERSION\', \'<%= pkg.version %>\' );', 33 | }, 34 | { 35 | from: /Tested up to:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 36 | to: 'Tested up to:$1' + pkg.tested_up_to, 37 | }, 38 | ], 39 | }, 40 | readme: { 41 | src: 'readme.*', 42 | overwrite: true, 43 | replacements: [ 44 | { 45 | from: /^(\*\*|)Stable tag:(\*\*|)(\s*?)[a-zA-Z0-9.-]+(\s*?)$/mi, 46 | to: '$1Stable tag:$2$3<%= pkg.version %>$4', 47 | }, 48 | { 49 | from: /Tested up to:(\s*?)[a-zA-Z0-9\.\-\+]+$/m, 50 | to: 'Tested up to:$1' + pkg.tested_up_to, 51 | }, 52 | ], 53 | }, 54 | tests: { 55 | src: '.dev/tests/phpunit/**/*.php', 56 | overwrite: true, 57 | replacements: [ 58 | { 59 | from: /\'version\'(\s*?)\=\>(\s*?)\'(.*)\'/, 60 | to: '\'version\' \=\> \'<%= pkg.version %>\'', 61 | }, 62 | ], 63 | }, 64 | languages: { 65 | src: 'languages/simple-taxonomy-ordering.pot', 66 | overwrite: true, 67 | replacements: [ 68 | { 69 | from: /(Project-Id-Version: Simple Taxonomy Ordering )[0-9\.]+/, 70 | to: '$1' + pkg.version, 71 | }, 72 | ], 73 | }, 74 | }, 75 | 76 | } ); 77 | 78 | grunt.loadNpmTasks( 'grunt-text-replace' ); 79 | 80 | grunt.registerTask( 'version', [ 'replace' ] ); 81 | }; 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | 676 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Simple Taxonomy Ordering 2 | 3 | 4 | 5 |

6 | 7 |

Quickly and easily reorder taxonomy terms with an easy to use and intuitive drag and drop interface.

8 | 9 |

10 | 11 | 12 | 13 | 14 | 15 | 16 |

17 | 18 |

19 | 20 | 21 | 22 | 23 | 24 | 25 |

26 | 27 |

28 | 29 | WordPress Versions 30 | 31 | 32 | PHP Versions 33 | 34 |

35 | 36 | Installation 37 | =========== 38 | 1. Install and activate the plugin 39 | 2. If you need to enable term sorting on default WordPress taxonomies, please see below. 40 | 3. If you would like to enable taxonomy term sorting on custom post type taxonomies, please see below. 41 | 4. Once enabled, you can drag & drop re-order your taxonomy terms. Whenever '[get_terms()](https://developer.wordpress.org/reference/functions/get_terms/)' is used to display your terms, they will display in the order you've set. 42 | 43 | Usage 44 | =========== 45 | 46 | #### Default WordPress Taxonomies 47 | After installing and activating the plugin, you have two options. You can enable drag & drop on any of the default taxonomies. To enable drag & drop sorting on default WordPress taxonomies, you'll want to assign the `tax_position` parameter to the register_post_type call. 48 | 49 | The easiest way to do so, is to use the following [snippet](https://gist.github.com/EvanHerman/4e83fda88d2b210dce95). 50 | 51 | ```php 52 | /* 53 | * Enable drag & drop sorting on default WordPress taxonomies (ie: categories) - (page/post) 54 | */ 55 | add_filter( 'register_taxonomy_args' , 'add_tax_position_support', PHP_INT_MAX, 3 ); 56 | function add_tax_position_support( $args, $taxonomy, $object_type ) { 57 | if( 'category' == $taxonomy ) { // Change the name of the taxonomy you want to enable drag&drop sort on 58 | $args['tax_position'] = true; 59 | } 60 | return $args; 61 | } 62 | ``` 63 | 64 | #### Custom Taxonomies 65 | Alternatively, if you've defined a custom taxonomy that you'd like to allow drag & drop sorting on, you'll want to pass in a `tax_position` parameter to the `$args` array inside of [register_taxonomy](https://codex.wordpress.org/Function_Reference/register_taxonomy). You can place this line directly after `'hierarchical'`. 66 | 67 | [Example Snippet](https://gist.github.com/EvanHerman/170e2a46db4cecdeb607) 68 | 69 | `'tax_position' => true,` 70 | 71 | 72 | #### Front End 73 | On the front end of the site, anywhere [get_terms()](https://developer.wordpress.org/reference/functions/get_terms/) is used to query a set of taxonomy terms, they will be returned in the order of their position on the taxonomy list. No additional steps need to be taken on on your end. 74 | 75 | Example 76 | ========= 77 | ![Admin Taxonomy Sorting Usage](https://cldup.com/bFZrQxtCPT.gif) 78 | 79 | 80 | Frequently Asked Questions 81 | =========== 82 | 83 | ### Can I make default WordPress taxonomies drag and drop sortable? 84 | 85 | Indeed, you can! You'll have to assign the `'tax_position'` parameter to the taxonomy. You can do this easily, using the following [sample code snippet](https://gist.github.com/EvanHerman/4e83fda88d2b210dce95). 86 | 87 | **You'll notice in the code snippet, the taxonomy we are using is 'category' - but you can change this value to suit your needs.** 88 | 89 | ### I have a custom post type, but it won't let me drag and drop sort it's taxonomies. How come? 90 | 91 | As mentioned above, the taxonomies need to have the parameter `'tax_position' => true` assigned to it. If the taxonomy is missing this parameter the items won't actually be sortable. For an example of how to implement it, please see the following [code snippet](https://gist.github.com/EvanHerman/170e2a46db4cecdeb607). 92 | 93 | ### How does the taxonomy know what order to remain in? 94 | 95 | With the release of WordPress 4.4 came taxonomy meta data, which gets stored inside of the `wp_termmeta` table in the database. Each taxonomy is assigned an integer value related to it's position on the taxonomy list. 96 | 97 | Filters 98 | =========== 99 | * `yikes_simple_taxonomy_ordering_capabilities` - Filter to adjust who can access the 'Simple Taxonomy Ordering' settings page. 100 | * `yikes_simple_taxonomy_ordering_excluded_taxonomies` - Filter to add additional taxonomies or remove default taxonomies. Items in this array will **not** be displayed in the dropdown on the settings page, and thus cannot have drag and drop sorting enabled. 101 | 102 | Issues 103 | =========== 104 | If you're running into any issues, we would love to hear about it. Please head over to the [Simple Taxonomy Ordering Issue Tracker](https://wordpress.org/support/plugin/simple-taxonomy-ordering/) and create a new issue. 105 | 106 | _________________ 107 | 108 |
Originally built with by YIKES Inc. in Philadelphia, PA.
Now Maintained by Evan Herman in Lancaster, PA.
109 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | 2.3.4 / 2022-05-31 2 | =================== 3 | * Fixes custom order not being displayed on edit-tags pages. 4 | 5 | 2.3.3 6 | =================== 7 | * Housekeeping 8 | 9 | 2.3.2 10 | =================== 11 | * Fixes column span bug present after updating to WordPress 5.5. 12 | 13 | 2.3.0 14 | =================== 15 | * Fixes bug with illegal string offset when disabling taxonomies under certain conditions. 16 | 17 | 2.2.0 18 | =================== 19 | * Added action `yikes_sto_taxonomy_order_updated` to hook into updated Taxonomy event. Thanks @d4mation! 20 | 21 | 2.1.0 22 | =================== 23 | * Singleton Pattern. This approach makes removing the filter, which sets the custom order, a lot easier. 24 | 25 | 2.0.3 26 | =================== 27 | * Fixed uninstall method. The plugin should now uninstall and clean up after itself without error. 28 | 29 | 2.0.2 30 | =================== 31 | * Fixed footer callout URLs and placement. It should only display on the settings page now. 32 | 33 | 2.0.1 34 | =================== 35 | * Fixed an issue with PHP versions < 7 (renaming class method from `include` to `include_files`). 36 | * Fixed an issue where new taxonomies were not being saved. 37 | * Fixed an issue where the plugin's action link to the settings page was going to the admin dashboard. 38 | * Updated the plugin's pot file with the proper text domain. 39 | 40 | 2.0.0 41 | =================== 42 | * Completely rewrote the plugin: it is now fully WPCS linted, assets are minified, inline styles and javascript have been removed, nonces are included in AJAX requests. 43 | * Fixed bugs with defaulting a taxonomy's order. 44 | * Fixed bug where ordering on a subsequent page would overwrite the first page's order. 45 | 46 | 1.2.7 47 | =================== 48 | * Added some variable checks to prevent PHP Notices. 49 | 50 | 1.2.6 51 | =================== 52 | * Changed the global (localized) JS variable from `localized_data` to `simple_taxonomy_ordering_data` to avoid any potential conflicts. 53 | 54 | 1.2.5 55 | =================== 56 | * Fixed an issue where terms weren't being returned if the termmeta table was empty. A big thanks to @doppiogancio on GitHub for finding this and helping us reach the solution. 57 | 58 | 1.2.4 59 | =================== 60 | * Fixed a JS issue that occurs when HTML is added to category description. A big thanks to @mateuszbajak for finding this and fixing it! 61 | 62 | 1.2.3 63 | =================== 64 | * Fixed a bug where the same SQL join statement was being added to a query twice on the front end (props to @burisk for calling this out) 65 | 66 | 1.2.2 67 | =================== 68 | * Added a CAST call to order taxonomies as integers instead of strings (props to Timothy Couckuyt / @devplus_timo for calling this out) 69 | 70 | 1.2.1 71 | =================== 72 | * Removed the `disableSelection()` call to allow selection of quick edit fields 73 | 74 | 1.2 75 | =================== 76 | * Added i18n: added domain path, languages folder, .pot file, and load_text_domain() hook 77 | 78 | 1.1 79 | =================== 80 | * Reverted query, added missing ORDER BY argument. 81 | 82 | 1.0 83 | =================== 84 | * Altered the query run when ordering terms (Props to Daniel Schwab for the [pull request](https://github.com/yikesinc/yikes-inc-simple-taxonomy-ordering/pull/2). 85 | 86 | 0.1 87 | =================== 88 | * Initial release 89 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "evanherman/yikes-inc-simple-taxonomy-ordering", 3 | "description": "Custom drag & drop taxonomy ordering WordPress plugin.", 4 | "type": "wordpress-plugin", 5 | "license": "GPL-2.0-only", 6 | "config": { 7 | "platform": { 8 | "php": "7.3" 9 | } 10 | }, 11 | "require": { 12 | "php": ">=5.6" 13 | }, 14 | "require-dev": { 15 | "phpcompatibility/phpcompatibility-wp": "^2.1", 16 | "phpunit/phpunit": "^9", 17 | "squizlabs/php_codesniffer": "^3.5", 18 | "wp-cli/wp-cli-bundle": "^2.4", 19 | "wp-coding-standards/wpcs": "^2.3", 20 | "wp-phpunit/wp-phpunit": "^5.8", 21 | "yoast/phpunit-polyfills": "^1.0.1" 22 | }, 23 | "scripts": { 24 | "test": "@php ./vendor/bin/phpunit", 25 | "test:coverage": "@php ./vendor/bin/phpunit --coverage-html .dev/tests/php/coverage/", 26 | "post-install-cmd": [ 27 | "./vendor/bin/phpcs --config-set installed_paths ./vendor/wp-coding-standards/wpcs" 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /languages/simple-taxonomy-ordering.pot: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 Evan Herman 2 | # This file is distributed under the same license as the Simple Taxonomy Ordering plugin. 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: Simple Taxonomy Ordering 2.3.4\n" 6 | "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/yikes-inc-simple-taxonomy-ordering\n" 7 | "Last-Translator: FULL NAME \n" 8 | "Language-Team: LANGUAGE \n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "POT-Creation-Date: 2022-06-25T06:52:38+00:00\n" 13 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 | "X-Generator: WP-CLI 2.5.0\n" 15 | "X-Domain: simple-taxonomy-ordering\n" 16 | 17 | #. Plugin Name of the plugin 18 | #: build/simple-taxonomy-ordering/lib/options.php:104 19 | #: lib/options.php:90 20 | #: lib/options.php:91 21 | #: lib/options.php:106 22 | msgid "Simple Taxonomy Ordering" 23 | msgstr "" 24 | 25 | #. Description of the plugin 26 | msgid "Custom drag & drop taxonomy ordering." 27 | msgstr "" 28 | 29 | #. Author of the plugin 30 | msgid "Evan Herman" 31 | msgstr "" 32 | 33 | #. Author URI of the plugin 34 | msgid "https://www.evan-herman.com" 35 | msgstr "" 36 | 37 | #. translators: %1$s is a link to https://www.evan-herman.com 38 | #: build/simple-taxonomy-ordering/lib/options.php:72 39 | msgid "Simple Taxonomy Ordering is maintained by %1$s. If you are enjoying it, please leave a %2$s review!" 40 | msgstr "" 41 | 42 | #: build/simple-taxonomy-ordering/lib/options.php:88 43 | #: build/simple-taxonomy-ordering/lib/options.php:89 44 | msgid "Simple Tax. Ordering" 45 | msgstr "" 46 | 47 | #: build/simple-taxonomy-ordering/lib/options.php:132 48 | #: lib/options.php:134 49 | msgid "Enabled Taxonomies" 50 | msgstr "" 51 | 52 | #: build/simple-taxonomy-ordering/lib/options.php:143 53 | #: lib/options.php:145 54 | msgid "Enable or disable taxonomies from being orderable by using the dropdown." 55 | msgstr "" 56 | 57 | #: build/simple-taxonomy-ordering/lib/options.php:172 58 | #: lib/options.php:179 59 | msgid "Select which taxonomies you would like to enable drag & drop sorting on." 60 | msgstr "" 61 | 62 | #: build/simple-taxonomy-ordering/lib/options.php:175 63 | #: lib/options.php:182 64 | msgid "No Taxonomies Found." 65 | msgstr "" 66 | 67 | #: build/simple-taxonomy-ordering/yikes-custom-taxonomy-order.php:132 68 | msgid "Taxonomy Ordering" 69 | msgstr "" 70 | 71 | #: build/simple-taxonomy-ordering/yikes-custom-taxonomy-order.php:133 72 | #: yikes-custom-taxonomy-order.php:98 73 | msgid "To reposition a taxonomy in the list, simply click on a taxonomy and drag & drop it into the desired position. Each time you reposition a taxonomy, the data will update in the database and on the front end of your site." 74 | msgstr "" 75 | 76 | #: build/simple-taxonomy-ordering/yikes-custom-taxonomy-order.php:133 77 | #: yikes-custom-taxonomy-order.php:98 78 | msgid "Example" 79 | msgstr "" 80 | 81 | #: build/simple-taxonomy-ordering/yikes-custom-taxonomy-order.php:133 82 | #: yikes-custom-taxonomy-order.php:98 83 | msgid "Simple Taxonomy Ordering Demo" 84 | msgstr "" 85 | 86 | #. translators: %1$s is a link to https://www.evan-herman.com. %2$s is HTML markup for 5 stars. 87 | #: lib/options.php:74 88 | msgid "Simple Taxonomy Ordering was created by %1$s. If you are enjoying it, please leave us a %2$s review!" 89 | msgstr "" 90 | 91 | #. translators: %s is the taxonomy singular name. eg: Category 92 | #: yikes-custom-taxonomy-order.php:95 93 | msgid "%s Ordering" 94 | msgstr "" 95 | -------------------------------------------------------------------------------- /lib/css/select2.css: -------------------------------------------------------------------------------- 1 | .select2-container { 2 | box-sizing: border-box; 3 | display: inline-block; 4 | margin: 0; 5 | position: relative; 6 | vertical-align: middle; } 7 | .select2-container .select2-selection--single { 8 | box-sizing: border-box; 9 | cursor: pointer; 10 | display: block; 11 | height: 28px; 12 | user-select: none; 13 | -webkit-user-select: none; } 14 | .select2-container .select2-selection--single .select2-selection__rendered { 15 | display: block; 16 | padding-left: 8px; 17 | padding-right: 20px; 18 | overflow: hidden; 19 | text-overflow: ellipsis; 20 | white-space: nowrap; } 21 | .select2-container .select2-selection--single .select2-selection__clear { 22 | background-color: transparent; 23 | border: none; 24 | font-size: 1em; } 25 | .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { 26 | padding-right: 8px; 27 | padding-left: 20px; } 28 | .select2-container .select2-selection--multiple { 29 | box-sizing: border-box; 30 | cursor: pointer; 31 | display: block; 32 | min-height: 32px; 33 | user-select: none; 34 | -webkit-user-select: none; } 35 | .select2-container .select2-selection--multiple .select2-selection__rendered { 36 | display: inline; 37 | list-style: none; 38 | padding: 0; } 39 | .select2-container .select2-selection--multiple .select2-selection__clear { 40 | background-color: transparent; 41 | border: none; 42 | font-size: 1em; } 43 | .select2-container .select2-search--inline .select2-search__field { 44 | box-sizing: border-box; 45 | border: none; 46 | font-size: 100%; 47 | margin-top: 5px; 48 | margin-left: 5px; 49 | padding: 0; 50 | max-width: 100%; 51 | resize: none; 52 | height: 18px; 53 | vertical-align: bottom; 54 | font-family: sans-serif; 55 | overflow: hidden; 56 | word-break: keep-all; } 57 | .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { 58 | -webkit-appearance: none; } 59 | 60 | .select2-dropdown { 61 | background-color: white; 62 | border: 1px solid #aaa; 63 | border-radius: 4px; 64 | box-sizing: border-box; 65 | display: block; 66 | position: absolute; 67 | left: -100000px; 68 | width: 100%; 69 | z-index: 1051; } 70 | 71 | .select2-results { 72 | display: block; } 73 | 74 | .select2-results__options { 75 | list-style: none; 76 | margin: 0; 77 | padding: 0; } 78 | 79 | .select2-results__option { 80 | padding: 6px; 81 | user-select: none; 82 | -webkit-user-select: none; } 83 | 84 | .select2-results__option--selectable { 85 | cursor: pointer; } 86 | 87 | .select2-container--open .select2-dropdown { 88 | left: 0; } 89 | 90 | .select2-container--open .select2-dropdown--above { 91 | border-bottom: none; 92 | border-bottom-left-radius: 0; 93 | border-bottom-right-radius: 0; } 94 | 95 | .select2-container--open .select2-dropdown--below { 96 | border-top: none; 97 | border-top-left-radius: 0; 98 | border-top-right-radius: 0; } 99 | 100 | .select2-search--dropdown { 101 | display: block; 102 | padding: 4px; } 103 | .select2-search--dropdown .select2-search__field { 104 | padding: 4px; 105 | width: 100%; 106 | box-sizing: border-box; } 107 | .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { 108 | -webkit-appearance: none; } 109 | .select2-search--dropdown.select2-search--hide { 110 | display: none; } 111 | 112 | .select2-close-mask { 113 | border: 0; 114 | margin: 0; 115 | padding: 0; 116 | display: block; 117 | position: fixed; 118 | left: 0; 119 | top: 0; 120 | min-height: 100%; 121 | min-width: 100%; 122 | height: auto; 123 | width: auto; 124 | opacity: 0; 125 | z-index: 99; 126 | background-color: #fff; 127 | filter: alpha(opacity=0); } 128 | 129 | .select2-hidden-accessible { 130 | border: 0 !important; 131 | clip: rect(0 0 0 0) !important; 132 | -webkit-clip-path: inset(50%) !important; 133 | clip-path: inset(50%) !important; 134 | height: 1px !important; 135 | overflow: hidden !important; 136 | padding: 0 !important; 137 | position: absolute !important; 138 | width: 1px !important; 139 | white-space: nowrap !important; } 140 | 141 | .select2-container--default .select2-selection--single { 142 | background-color: #fff; 143 | border: 1px solid #aaa; 144 | border-radius: 4px; } 145 | .select2-container--default .select2-selection--single .select2-selection__rendered { 146 | color: #444; 147 | line-height: 28px; } 148 | .select2-container--default .select2-selection--single .select2-selection__clear { 149 | cursor: pointer; 150 | float: right; 151 | font-weight: bold; 152 | height: 26px; 153 | margin-right: 20px; 154 | padding-right: 0px; } 155 | .select2-container--default .select2-selection--single .select2-selection__placeholder { 156 | color: #999; } 157 | .select2-container--default .select2-selection--single .select2-selection__arrow { 158 | height: 26px; 159 | position: absolute; 160 | top: 1px; 161 | right: 1px; 162 | width: 20px; } 163 | .select2-container--default .select2-selection--single .select2-selection__arrow b { 164 | border-color: #888 transparent transparent transparent; 165 | border-style: solid; 166 | border-width: 5px 4px 0 4px; 167 | height: 0; 168 | left: 50%; 169 | margin-left: -4px; 170 | margin-top: -2px; 171 | position: absolute; 172 | top: 50%; 173 | width: 0; } 174 | 175 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { 176 | float: left; } 177 | 178 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { 179 | left: 1px; 180 | right: auto; } 181 | 182 | .select2-container--default.select2-container--disabled .select2-selection--single { 183 | background-color: #eee; 184 | cursor: default; } 185 | .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { 186 | display: none; } 187 | 188 | .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { 189 | border-color: transparent transparent #888 transparent; 190 | border-width: 0 4px 5px 4px; } 191 | 192 | .select2-container--default .select2-selection--multiple { 193 | background-color: white; 194 | border: 1px solid #aaa; 195 | border-radius: 4px; 196 | cursor: text; 197 | padding-bottom: 5px; 198 | padding-right: 5px; 199 | position: relative; } 200 | .select2-container--default .select2-selection--multiple.select2-selection--clearable { 201 | padding-right: 25px; } 202 | .select2-container--default .select2-selection--multiple .select2-selection__clear { 203 | cursor: pointer; 204 | font-weight: bold; 205 | height: 20px; 206 | margin-right: 10px; 207 | margin-top: 5px; 208 | position: absolute; 209 | right: 0; 210 | padding: 1px; } 211 | .select2-container--default .select2-selection--multiple .select2-selection__choice { 212 | background-color: #e4e4e4; 213 | border: 1px solid #aaa; 214 | border-radius: 4px; 215 | box-sizing: border-box; 216 | display: inline-block; 217 | margin-left: 5px; 218 | margin-top: 5px; 219 | padding: 0; 220 | padding-left: 20px; 221 | position: relative; 222 | max-width: 100%; 223 | overflow: hidden; 224 | text-overflow: ellipsis; 225 | vertical-align: bottom; 226 | white-space: nowrap; } 227 | .select2-container--default .select2-selection--multiple .select2-selection__choice__display { 228 | cursor: default; 229 | padding-left: 2px; 230 | padding-right: 5px; } 231 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { 232 | background-color: transparent; 233 | border: none; 234 | border-right: 1px solid #aaa; 235 | border-top-left-radius: 4px; 236 | border-bottom-left-radius: 4px; 237 | color: #999; 238 | cursor: pointer; 239 | font-size: 1em; 240 | font-weight: bold; 241 | padding: 0 4px; 242 | position: absolute; 243 | left: 0; 244 | top: 0; } 245 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:focus { 246 | background-color: #f1f1f1; 247 | color: #333; 248 | outline: none; } 249 | 250 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 251 | margin-left: 5px; 252 | margin-right: auto; } 253 | 254 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display { 255 | padding-left: 5px; 256 | padding-right: 2px; } 257 | 258 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 259 | border-left: 1px solid #aaa; 260 | border-right: none; 261 | border-top-left-radius: 0; 262 | border-bottom-left-radius: 0; 263 | border-top-right-radius: 4px; 264 | border-bottom-right-radius: 4px; } 265 | 266 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__clear { 267 | float: left; 268 | margin-left: 10px; 269 | margin-right: auto; } 270 | 271 | .select2-container--default.select2-container--focus .select2-selection--multiple { 272 | border: solid black 1px; 273 | outline: 0; } 274 | 275 | .select2-container--default.select2-container--disabled .select2-selection--multiple { 276 | background-color: #eee; 277 | cursor: default; } 278 | 279 | .select2-container--default.select2-container--disabled .select2-selection__choice__remove { 280 | display: none; } 281 | 282 | .select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { 283 | border-top-left-radius: 0; 284 | border-top-right-radius: 0; } 285 | 286 | .select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { 287 | border-bottom-left-radius: 0; 288 | border-bottom-right-radius: 0; } 289 | 290 | .select2-container--default .select2-search--dropdown .select2-search__field { 291 | border: 1px solid #aaa; } 292 | 293 | .select2-container--default .select2-search--inline .select2-search__field { 294 | background: transparent; 295 | border: none; 296 | outline: 0; 297 | box-shadow: none; 298 | -webkit-appearance: textfield; } 299 | 300 | .select2-container--default .select2-results > .select2-results__options { 301 | max-height: 200px; 302 | overflow-y: auto; } 303 | 304 | .select2-container--default .select2-results__option .select2-results__option { 305 | padding-left: 1em; } 306 | .select2-container--default .select2-results__option .select2-results__option .select2-results__group { 307 | padding-left: 0; } 308 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option { 309 | margin-left: -1em; 310 | padding-left: 2em; } 311 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 312 | margin-left: -2em; 313 | padding-left: 3em; } 314 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 315 | margin-left: -3em; 316 | padding-left: 4em; } 317 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 318 | margin-left: -4em; 319 | padding-left: 5em; } 320 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 321 | margin-left: -5em; 322 | padding-left: 6em; } 323 | 324 | .select2-container--default .select2-results__option--group { 325 | padding: 0; } 326 | 327 | .select2-container--default .select2-results__option--disabled { 328 | color: #999; } 329 | 330 | .select2-container--default .select2-results__option--selected { 331 | background-color: #ddd; } 332 | 333 | .select2-container--default .select2-results__option--highlighted.select2-results__option--selectable { 334 | background-color: #5897fb; 335 | color: white; } 336 | 337 | .select2-container--default .select2-results__group { 338 | cursor: default; 339 | display: block; 340 | padding: 6px; } 341 | 342 | .select2-container--classic .select2-selection--single { 343 | background-color: #f7f7f7; 344 | border: 1px solid #aaa; 345 | border-radius: 4px; 346 | outline: 0; 347 | background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); 348 | background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); 349 | background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); 350 | background-repeat: repeat-x; 351 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 352 | .select2-container--classic .select2-selection--single:focus { 353 | border: 1px solid #5897fb; } 354 | .select2-container--classic .select2-selection--single .select2-selection__rendered { 355 | color: #444; 356 | line-height: 28px; } 357 | .select2-container--classic .select2-selection--single .select2-selection__clear { 358 | cursor: pointer; 359 | float: right; 360 | font-weight: bold; 361 | height: 26px; 362 | margin-right: 20px; } 363 | .select2-container--classic .select2-selection--single .select2-selection__placeholder { 364 | color: #999; } 365 | .select2-container--classic .select2-selection--single .select2-selection__arrow { 366 | background-color: #ddd; 367 | border: none; 368 | border-left: 1px solid #aaa; 369 | border-top-right-radius: 4px; 370 | border-bottom-right-radius: 4px; 371 | height: 26px; 372 | position: absolute; 373 | top: 1px; 374 | right: 1px; 375 | width: 20px; 376 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 377 | background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 378 | background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); 379 | background-repeat: repeat-x; 380 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } 381 | .select2-container--classic .select2-selection--single .select2-selection__arrow b { 382 | border-color: #888 transparent transparent transparent; 383 | border-style: solid; 384 | border-width: 5px 4px 0 4px; 385 | height: 0; 386 | left: 50%; 387 | margin-left: -4px; 388 | margin-top: -2px; 389 | position: absolute; 390 | top: 50%; 391 | width: 0; } 392 | 393 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { 394 | float: left; } 395 | 396 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { 397 | border: none; 398 | border-right: 1px solid #aaa; 399 | border-radius: 0; 400 | border-top-left-radius: 4px; 401 | border-bottom-left-radius: 4px; 402 | left: 1px; 403 | right: auto; } 404 | 405 | .select2-container--classic.select2-container--open .select2-selection--single { 406 | border: 1px solid #5897fb; } 407 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { 408 | background: transparent; 409 | border: none; } 410 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { 411 | border-color: transparent transparent #888 transparent; 412 | border-width: 0 4px 5px 4px; } 413 | 414 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { 415 | border-top: none; 416 | border-top-left-radius: 0; 417 | border-top-right-radius: 0; 418 | background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); 419 | background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); 420 | background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); 421 | background-repeat: repeat-x; 422 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 423 | 424 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { 425 | border-bottom: none; 426 | border-bottom-left-radius: 0; 427 | border-bottom-right-radius: 0; 428 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); 429 | background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); 430 | background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); 431 | background-repeat: repeat-x; 432 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } 433 | 434 | .select2-container--classic .select2-selection--multiple { 435 | background-color: white; 436 | border: 1px solid #aaa; 437 | border-radius: 4px; 438 | cursor: text; 439 | outline: 0; 440 | padding-bottom: 5px; 441 | padding-right: 5px; } 442 | .select2-container--classic .select2-selection--multiple:focus { 443 | border: 1px solid #5897fb; } 444 | .select2-container--classic .select2-selection--multiple .select2-selection__clear { 445 | display: none; } 446 | .select2-container--classic .select2-selection--multiple .select2-selection__choice { 447 | background-color: #e4e4e4; 448 | border: 1px solid #aaa; 449 | border-radius: 4px; 450 | display: inline-block; 451 | margin-left: 5px; 452 | margin-top: 5px; 453 | padding: 0; } 454 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__display { 455 | cursor: default; 456 | padding-left: 2px; 457 | padding-right: 5px; } 458 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { 459 | background-color: transparent; 460 | border: none; 461 | border-top-left-radius: 4px; 462 | border-bottom-left-radius: 4px; 463 | color: #888; 464 | cursor: pointer; 465 | font-size: 1em; 466 | font-weight: bold; 467 | padding: 0 4px; } 468 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { 469 | color: #555; 470 | outline: none; } 471 | 472 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 473 | margin-left: 5px; 474 | margin-right: auto; } 475 | 476 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display { 477 | padding-left: 5px; 478 | padding-right: 2px; } 479 | 480 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 481 | border-top-left-radius: 0; 482 | border-bottom-left-radius: 0; 483 | border-top-right-radius: 4px; 484 | border-bottom-right-radius: 4px; } 485 | 486 | .select2-container--classic.select2-container--open .select2-selection--multiple { 487 | border: 1px solid #5897fb; } 488 | 489 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { 490 | border-top: none; 491 | border-top-left-radius: 0; 492 | border-top-right-radius: 0; } 493 | 494 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { 495 | border-bottom: none; 496 | border-bottom-left-radius: 0; 497 | border-bottom-right-radius: 0; } 498 | 499 | .select2-container--classic .select2-search--dropdown .select2-search__field { 500 | border: 1px solid #aaa; 501 | outline: 0; } 502 | 503 | .select2-container--classic .select2-search--inline .select2-search__field { 504 | outline: 0; 505 | box-shadow: none; } 506 | 507 | .select2-container--classic .select2-dropdown { 508 | background-color: white; 509 | border: 1px solid transparent; } 510 | 511 | .select2-container--classic .select2-dropdown--above { 512 | border-bottom: none; } 513 | 514 | .select2-container--classic .select2-dropdown--below { 515 | border-top: none; } 516 | 517 | .select2-container--classic .select2-results > .select2-results__options { 518 | max-height: 200px; 519 | overflow-y: auto; } 520 | 521 | .select2-container--classic .select2-results__option--group { 522 | padding: 0; } 523 | 524 | .select2-container--classic .select2-results__option--disabled { 525 | color: grey; } 526 | 527 | .select2-container--classic .select2-results__option--highlighted.select2-results__option--selectable { 528 | background-color: #3875d7; 529 | color: white; } 530 | 531 | .select2-container--classic .select2-results__group { 532 | cursor: default; 533 | display: block; 534 | padding: 6px; } 535 | 536 | .select2-container--classic.select2-container--open .select2-dropdown { 537 | border-color: #5897fb; } 538 | -------------------------------------------------------------------------------- /lib/css/select2.min.css: -------------------------------------------------------------------------------- 1 | .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.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;list-style:none;padding:0}.select2-container .select2-selection--multiple .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;margin-left:5px;padding:0;max-width:100%;resize:none;height:18px;vertical-align:bottom;font-family:sans-serif;overflow:hidden;word-break:keep-all}.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--selectable{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;height:26px;margin-right:20px;padding-right:0px}.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;padding-bottom:5px;padding-right:5px;position:relative}.select2-container--default .select2-selection--multiple.select2-selection--clearable{padding-right:25px}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;font-weight:bold;height:20px;margin-right:10px;margin-top:5px;position:absolute;right:0;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:inline-block;margin-left:5px;margin-top:5px;padding:0;padding-left:20px;position:relative;max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom;white-space:nowrap}.select2-container--default .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-right:1px solid #aaa;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#999;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px;position:absolute;left:0;top:0}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover,.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:focus{background-color:#f1f1f1;color:#333;outline:none}.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__display{padding-left:5px;padding-right:2px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-left:1px solid #aaa;border-right:none;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__clear{float:left;margin-left:10px;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 .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--group{padding:0}.select2-container--default .select2-results__option--disabled{color:#999}.select2-container--default .select2-results__option--selected{background-color:#ddd}.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable{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;height:26px;margin-right:20px}.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;padding-bottom:5px;padding-right:5px}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.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;display:inline-block;margin-left:5px;margin-top:5px;padding:0}.select2-container--classic .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#888;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555;outline:none}.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__display{padding-left:5px;padding-right:2px}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.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--group{padding:0}.select2-container--classic .select2-results__option--disabled{color:grey}.select2-container--classic .select2-results__option--highlighted.select2-results__option--selectable{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} 2 | -------------------------------------------------------------------------------- /lib/css/yikes-tax-drag-drop.css: -------------------------------------------------------------------------------- 1 | /* Simple Taxonomy Ordering Styles. */ 2 | .yikes-drag-drop-tax-placeholder { 3 | min-height: 57px; 4 | height: 100%; 5 | } 6 | 7 | #the-list tr:hover { 8 | cursor: grab; 9 | } 10 | 11 | #the-list tr.ui-sortable-helper:hover { 12 | display: table; 13 | cursor: grabbing; 14 | } 15 | 16 | #the-list tr.no-items:hover { 17 | cursor: default; 18 | } 19 | 20 | .yikes-simple-taxonomy-preloader { 21 | margin: 0 0 0 8px; 22 | } 23 | -------------------------------------------------------------------------------- /lib/css/yikes-tax-drag-drop.min.css: -------------------------------------------------------------------------------- 1 | .yikes-drag-drop-tax-placeholder{min-height:57px;height:100%}#the-list tr:hover{cursor:grab}#the-list tr.ui-sortable-helper:hover{display:table;cursor:grabbing}#the-list tr.no-items:hover{cursor:default}.yikes-simple-taxonomy-preloader{margin:0 0 0 8px} 2 | -------------------------------------------------------------------------------- /lib/img/sort-category-help-example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvanHerman/simple-taxonomy-ordering/6ba5fabf0bd0f18f04b6b0088229e73286549db1/lib/img/sort-category-help-example.gif -------------------------------------------------------------------------------- /lib/js/select2.min.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.1.0-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | !function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(t){var e,n,s,p,r,o,h,f,g,m,y,v,i,a,_,s=(t&&t.fn&&t.fn.select2&&t.fn.select2.amd&&(u=t.fn.select2.amd),u&&u.requirejs||(u?n=u:u={},g={},m={},y={},v={},i=Object.prototype.hasOwnProperty,a=[].slice,_=/\.js$/,h=function(e,t){var n,s,i=c(e),r=i[0],t=t[1];return e=i[1],r&&(n=x(r=l(r,t))),r?e=n&&n.normalize?n.normalize(e,(s=t,function(e){return l(e,s)})):l(e,t):(r=(i=c(e=l(e,t)))[0],e=i[1],r&&(n=x(r))),{f:r?r+"!"+e:e,n:e,pr:r,p:n}},f={require:function(e){return w(e)},exports:function(e){var t=g[e];return void 0!==t?t:g[e]={}},module:function(e){return{id:e,uri:"",exports:g[e],config:(t=e,function(){return y&&y.config&&y.config[t]||{}})};var t}},r=function(e,t,n,s){var i,r,o,a,l,c=[],u=typeof n,d=A(s=s||e);if("undefined"==u||"function"==u){for(t=!t.length&&n.length?["require","exports","module"]:t,a=0;a":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},s.__cache={};var n=0;return s.GetUniqueElementId=function(e){var t=e.getAttribute("data-select2-id");return null!=t||(t=e.id?"select2-data-"+e.id:"select2-data-"+(++n).toString()+"-"+s.generateChars(4),e.setAttribute("data-select2-id",t)),t},s.StoreData=function(e,t,n){e=s.GetUniqueElementId(e);s.__cache[e]||(s.__cache[e]={}),s.__cache[e][t]=n},s.GetData=function(e,t){var n=s.GetUniqueElementId(e);return t?s.__cache[n]&&null!=s.__cache[n][t]?s.__cache[n][t]:r(e).data(t):s.__cache[n]},s.RemoveData=function(e){var t=s.GetUniqueElementId(e);null!=s.__cache[t]&&delete s.__cache[t],e.removeAttribute("data-select2-id")},s.copyNonInternalCssClasses=function(e,t){var n=(n=e.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0===e.indexOf("select2-")}),t=(t=t.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0!==e.indexOf("select2-")}),t=n.concat(t);e.setAttribute("class",t.join(" "))},s}),u.define("select2/results",["jquery","./utils"],function(d,p){function s(e,t,n){this.$element=e,this.data=n,this.options=t,s.__super__.constructor.call(this)}return p.Extend(s,p.Observable),s.prototype.render=function(){var e=d('
    ');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},s.prototype.clear=function(){this.$results.empty()},s.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=d(''),s=this.options.get("translations").get(e.message);n.append(t(s(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},s.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},s.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n",{class:"select2-results__options select2-results__options--nested",role:"none"});i.append(l),o.append(a),o.append(i)}else this.template(e,t);return p.StoreData(t,"data",e),t},s.prototype.bind=function(t,e){var i=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){i.clear(),i.append(e.data),t.isOpen()&&(i.setClasses(),i.highlightFirstItem())}),t.on("results:append",function(e){i.append(e.data),t.isOpen()&&i.setClasses()}),t.on("query",function(e){i.hideMessages(),i.showLoading(e)}),t.on("select",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("open",function(){i.$results.attr("aria-expanded","true"),i.$results.attr("aria-hidden","false"),i.setClasses(),i.ensureHighlightVisible()}),t.on("close",function(){i.$results.attr("aria-expanded","false"),i.$results.attr("aria-hidden","true"),i.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=i.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e,t=i.getHighlightedResults();0!==t.length&&(e=p.GetData(t[0],"data"),t.hasClass("select2-results__option--selected")?i.trigger("close",{}):i.trigger("select",{data:e}))}),t.on("results:previous",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t);s<=0||(e=s-1,0===t.length&&(e=0),(s=n.eq(e)).trigger("mouseenter"),t=i.$results.offset().top,n=s.offset().top,s=i.$results.scrollTop()+(n-t),0===e?i.$results.scrollTop(0):n-t<0&&i.$results.scrollTop(s))}),t.on("results:next",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t)+1;s>=n.length||((e=n.eq(s)).trigger("mouseenter"),t=i.$results.offset().top+i.$results.outerHeight(!1),n=e.offset().top+e.outerHeight(!1),e=i.$results.scrollTop()+n-t,0===s?i.$results.scrollTop(0):tthis.$results.outerHeight()||s<0)&&this.$results.scrollTop(n))},s.prototype.template=function(e,t){var n=this.options.get("templateResult"),s=this.options.get("escapeMarkup"),e=n(e,t);null==e?t.style.display="none":"string"==typeof e?t.innerHTML=s(e):d(t).append(e)},s}),u.define("select2/keys",[],function(){return{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}}),u.define("select2/selection/base",["jquery","../utils","../keys"],function(n,s,i){function r(e,t){this.$element=e,this.options=t,r.__super__.constructor.call(this)}return s.Extend(r,s.Observable),r.prototype.render=function(){var e=n('');return this._tabindex=0,null!=s.GetData(this.$element[0],"old-tabindex")?this._tabindex=s.GetData(this.$element[0],"old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),e.attr("aria-disabled","false"),this.$selection=e},r.prototype.bind=function(e,t){var n=this,s=e.id+"-results";this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===i.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",s),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),n.$selection.trigger("focus"),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex),n.$selection.attr("aria-disabled","false")}),e.on("disable",function(){n.$selection.attr("tabindex","-1"),n.$selection.attr("aria-disabled","true")})},r.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},r.prototype._attachCloseHandler=function(e){n(document.body).on("mousedown.select2."+e.id,function(e){var t=n(e.target).closest(".select2");n(".select2.select2-container--open").each(function(){this!=t[0]&&s.GetData(this,"element").select2("close")})})},r.prototype._detachCloseHandler=function(e){n(document.body).off("mousedown.select2."+e.id)},r.prototype.position=function(e,t){t.find(".selection").append(e)},r.prototype.destroy=function(){this._detachCloseHandler(this.container)},r.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},r.prototype.isEnabled=function(){return!this.isDisabled()},r.prototype.isDisabled=function(){return this.options.get("disabled")},r}),u.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,s){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e[0].classList.add("select2-selection--single"),e.html(''),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var s=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",s),this.$selection.attr("aria-controls",s),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.trigger("focus")})},i.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},i.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},i.prototype.selectionContainer=function(){return e("")},i.prototype.update=function(e){var t,n;0!==e.length?(n=e[0],t=this.$selection.find(".select2-selection__rendered"),e=this.display(n,t),t.empty().append(e),(n=n.title||n.text)?t.attr("title",n):t.removeAttr("title")):this.clear()},i}),u.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,c){function r(e,t){r.__super__.constructor.apply(this,arguments)}return c.Extend(r,e),r.prototype.render=function(){var e=r.__super__.render.call(this);return e[0].classList.add("select2-selection--multiple"),e.html('
      '),e},r.prototype.bind=function(e,t){var n=this;r.__super__.bind.apply(this,arguments);var s=e.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s),this.$selection.on("click",function(e){n.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){var t;n.isDisabled()||(t=i(this).parent(),t=c.GetData(t[0],"data"),n.trigger("unselect",{originalEvent:e,data:t}))}),this.$selection.on("keydown",".select2-selection__choice__remove",function(e){n.isDisabled()||e.stopPropagation()})},r.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},r.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},r.prototype.selectionContainer=function(){return i('
    • ')},r.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=this.$selection.find(".select2-selection__rendered").attr("id")+"-choice-",s=0;s')).attr("title",s()),e.attr("aria-label",s()),e.attr("aria-describedby",n),a.StoreData(e[0],"data",t),this.$selection.prepend(e),this.$selection[0].classList.add("select2-selection--clearable"))},e}),u.define("select2/selection/search",["jquery","../utils","../keys"],function(s,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=this.options.get("translations").get("search"),n=s('');this.$searchContainer=n,this.$search=n.find("textarea"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",t());e=e.call(this);return this._transferTabIndex(),e.append(this.$searchContainer),e},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results",r=t.id+"-container";e.call(this,t,n),s.$search.attr("aria-describedby",r),t.on("open",function(){s.$search.attr("aria-controls",i),s.$search.trigger("focus")}),t.on("close",function(){s.$search.val(""),s.resizeSearch(),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.trigger("focus")}),t.on("enable",function(){s.$search.prop("disabled",!1),s._transferTabIndex()}),t.on("disable",function(){s.$search.prop("disabled",!0)}),t.on("focus",function(e){s.$search.trigger("focus")}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")}),this.$selection.on("focusin",".select2-search--inline",function(e){s.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){s._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){var t;e.stopPropagation(),s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented(),e.which!==l.BACKSPACE||""!==s.$search.val()||0<(t=s.$selection.find(".select2-selection__choice").last()).length&&(t=a.GetData(t[0],"data"),s.searchRemoveChoice(t),e.preventDefault())}),this.$selection.on("click",".select2-search--inline",function(e){s.$search.val()&&e.stopPropagation()});var t=document.documentMode,o=t&&t<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(e){o?s.$selection.off("input.search input.searchcheck"):s.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(e){var t;o&&"input"===e.type?s.$selection.off("input.search input.searchcheck"):(t=e.which)!=l.SHIFT&&t!=l.CTRL&&t!=l.ALT&&t!=l.TAB&&s.handleSearch(e)})},e.prototype._transferTabIndex=function(e){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},e.prototype.createPlaceholder=function(e,t){this.$search.attr("placeholder",t.text)},e.prototype.update=function(e,t){var n=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),e.call(this,t),this.resizeSearch(),n&&this.$search.trigger("focus")},e.prototype.handleSearch=function(){var e;this.resizeSearch(),this._keyUpPrevented||(e=this.$search.val(),this.trigger("query",{term:e})),this._keyUpPrevented=!1},e.prototype.searchRemoveChoice=function(e,t){this.trigger("unselect",{data:t}),this.$search.val(t.text),this.handleSearch()},e.prototype.resizeSearch=function(){this.$search.css("width","25px");var e="100%";""===this.$search.attr("placeholder")&&(e=.75*(this.$search.val().length+1)+"em"),this.$search.css("width",e)},e}),u.define("select2/selection/selectionCss",["../utils"],function(n){function e(){}return e.prototype.render=function(e){var t=e.call(this),e=this.options.get("selectionCssClass")||"";return-1!==e.indexOf(":all:")&&(e=e.replace(":all:",""),n.copyNonInternalCssClasses(t[0],this.$element[0])),t.addClass(e),t},e}),u.define("select2/selection/eventRelay",["jquery"],function(o){function e(){}return e.prototype.bind=function(e,t,n){var s=this,i=["open","opening","close","closing","select","selecting","unselect","unselecting","clear","clearing"],r=["opening","closing","selecting","unselecting","clearing"];e.call(this,t,n),t.on("*",function(e,t){var n;-1!==i.indexOf(e)&&(t=t||{},n=o.Event("select2:"+e,{params:t}),s.$element.trigger(n),-1!==r.indexOf(e)&&(t.prevented=n.isDefaultPrevented()))})},e}),u.define("select2/translation",["jquery","require"],function(t,n){function s(e){this.dict=e||{}}return s.prototype.all=function(){return this.dict},s.prototype.get=function(e){return this.dict[e]},s.prototype.extend=function(e){this.dict=t.extend({},e.all(),this.dict)},s._cache={},s.loadPath=function(e){var t;return e in s._cache||(t=n(e),s._cache[e]=t),new s(s._cache[e])},s}),u.define("select2/diacritics",[],function(){return{"Ⓐ":"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","Œ":"OE","Ƣ":"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","œ":"oe","ƣ":"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","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ώ":"ω","ς":"σ","’":"'"}}),u.define("select2/data/base",["../utils"],function(n){function s(e,t){s.__super__.constructor.call(this)}return n.Extend(s,n.Observable),s.prototype.current=function(e){throw new Error("The `current` method must be defined in child classes.")},s.prototype.query=function(e,t){throw new Error("The `query` method must be defined in child classes.")},s.prototype.bind=function(e,t){},s.prototype.destroy=function(){},s.prototype.generateResultId=function(e,t){e=e.id+"-result-";return e+=n.generateChars(4),null!=t.id?e+="-"+t.id.toString():e+="-"+n.generateChars(4),e},s}),u.define("select2/data/select",["./base","../utils","jquery"],function(e,a,l){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return a.Extend(n,e),n.prototype.current=function(e){var t=this;e(Array.prototype.map.call(this.$element[0].querySelectorAll(":checked"),function(e){return t.item(l(e))}))},n.prototype.select=function(i){var e,r=this;if(i.selected=!0,null!=i.element&&"option"===i.element.tagName.toLowerCase())return i.element.selected=!0,void this.$element.trigger("input").trigger("change");this.$element.prop("multiple")?this.current(function(e){var t=[];(i=[i]).push.apply(i,e);for(var n=0;nthis.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),u.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("select",function(){s._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var s=this;this._checkIfMaximumSelected(function(){e.call(s,t,n)})},e.prototype._checkIfMaximumSelected=function(e,t){var n=this;this.current(function(e){e=null!=e?e.length:0;0=n.maximumSelectionLength?n.trigger("results:message",{message:"maximumSelected",args:{maximum:n.maximumSelectionLength}}):t&&t()})},e}),u.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),u.define("select2/dropdown/search",["jquery"],function(r){function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("translations").get("search"),e=r('');return this.$searchContainer=e,this.$search=e.find("input"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",n()),t.prepend(e),t},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){r(this).off("keyup")}),this.$search.on("keyup input",function(e){s.handleSearch(e)}),t.on("open",function(){s.$search.attr("tabindex",0),s.$search.attr("aria-controls",i),s.$search.trigger("focus"),window.setTimeout(function(){s.$search.trigger("focus")},0)}),t.on("close",function(){s.$search.attr("tabindex",-1),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.val(""),s.$search.trigger("blur")}),t.on("focus",function(){t.isOpen()||s.$search.trigger("focus")}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(s.showSearch(e)?s.$searchContainer[0].classList.remove("select2-search--hide"):s.$searchContainer[0].classList.add("select2-search--hide"))}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")})},e.prototype.handleSearch=function(e){var t;this._keyUpPrevented||(t=this.$search.val(),this.trigger("query",{term:t})),this._keyUpPrevented=!1},e.prototype.showSearch=function(e,t){return!0},e}),u.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,s){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,s)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),s=t.length-1;0<=s;s--){var i=t[s];this.placeholder.id===i.id&&n.splice(s,1)}return n},e}),u.define("select2/dropdown/infiniteScroll",["jquery"],function(n){function e(e,t,n,s){this.lastParams={},e.call(this,t,n,s),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("query",function(e){s.lastParams=e,s.loading=!0}),t.on("query:append",function(e){s.lastParams=e,s.loading=!0}),this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);!this.loading&&e&&(e=this.$results.offset().top+this.$results.outerHeight(!1),this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)<=e+50&&this.loadMore())},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=n('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),u.define("select2/dropdown/attachBody",["jquery","../utils"],function(u,o){function e(e,t,n){this.$dropdownParent=u(n.get("dropdownParent")||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("open",function(){s._showDropdown(),s._attachPositioningHandler(t),s._bindContainerResultHandlers(t)}),t.on("close",function(){s._hideDropdown(),s._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t[0].classList.remove("select2"),t[0].classList.add("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=u(""),e=e.call(this);return t.append(e),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){var n;this._containerResultsHandlersBound||(n=this,t.on("results:all",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:append",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:message",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("select",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("unselect",function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0)},e.prototype._attachPositioningHandler=function(e,t){var n=this,s="scroll.select2."+t.id,i="resize.select2."+t.id,r="orientationchange.select2."+t.id,t=this.$container.parents().filter(o.hasScroll);t.each(function(){o.StoreData(this,"select2-scroll-position",{x:u(this).scrollLeft(),y:u(this).scrollTop()})}),t.on(s,function(e){var t=o.GetData(this,"select2-scroll-position");u(this).scrollTop(t.y)}),u(window).on(s+" "+i+" "+r,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,s="resize.select2."+t.id,t="orientationchange.select2."+t.id;this.$container.parents().filter(o.hasScroll).off(n),u(window).off(n+" "+s+" "+t)},e.prototype._positionDropdown=function(){var e=u(window),t=this.$dropdown[0].classList.contains("select2-dropdown--above"),n=this.$dropdown[0].classList.contains("select2-dropdown--below"),s=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var r={height:this.$container.outerHeight(!1)};r.top=i.top,r.bottom=i.top+r.height;var o=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ai.bottom+o,a={left:i.left,top:r.bottom},l=this.$dropdownParent;"static"===l.css("position")&&(l=l.offsetParent());i={top:0,left:0};(u.contains(document.body,l[0])||l[0].isConnected)&&(i=l.offset()),a.top-=i.top,a.left-=i.left,t||n||(s="below"),e||!c||t?!c&&e&&t&&(s="below"):s="above",("above"==s||t&&"below"!==s)&&(a.top=r.top-i.top-o),null!=s&&(this.$dropdown[0].classList.remove("select2-dropdown--below"),this.$dropdown[0].classList.remove("select2-dropdown--above"),this.$dropdown[0].classList.add("select2-dropdown--"+s),this.$container[0].classList.remove("select2-container--below"),this.$container[0].classList.remove("select2-container--above"),this.$container[0].classList.add("select2-container--"+s)),this.$dropdownContainer.css(a)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),u.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,s){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,s)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,s=0;s');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container[0].classList.add("select2-container--"+this.options.get("theme")),r.StoreData(e[0],"element",this.$element),e},o}),u.define("jquery-mousewheel",["jquery"],function(e){return e}),u.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function(i,e,r,t,o){var a;return null==i.fn.select2&&(a=["open","close","destroy"],i.fn.select2=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new r(i(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,s=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=o.GetData(this,"select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,s)}),-1 0 ? ( parseInt( simple_taxonomy_ordering_data.paged ) - 1 ) * parseInt( $( '#' + simple_taxonomy_ordering_data.per_page_id ).val() ) : 0; 6 | const tax_table = $( '#the-list' ); 7 | 8 | // If the tax table contains items. 9 | if ( ! tax_table.find( 'tr:first-child' ).hasClass( 'no-items' ) ) { 10 | 11 | tax_table.sortable({ 12 | placeholder: "yikes-drag-drop-tax-placeholder", 13 | axis: "y", 14 | 15 | // On start, set a height for the placeholder to prevent table jumps. 16 | start: function( event, ui ) { 17 | const item = $( ui.item[0] ); 18 | $( '.yikes-drag-drop-tax-placeholder' ) 19 | .css( 'height', item.css( 'height' ) ) 20 | .css( 'display', 'flex' ) 21 | .css( 'width', '0' ); 22 | }, 23 | // Update callback. 24 | update: function( event, ui ) { 25 | const item = $( ui.item[0] ); 26 | 27 | // Hide checkbox, append a preloader. 28 | item.find( 'input[type="checkbox"]' ).hide().after( '' ); 29 | 30 | const taxonomy_ordering_data = []; 31 | 32 | tax_table.find( 'tr.ui-sortable-handle' ).each( function() { 33 | const ele = $( this ); 34 | const term_data = { 35 | term_id: ele.attr( 'id' ).replace( 'tag-', '' ), 36 | order: parseInt( ele.index() ) + 1 37 | } 38 | taxonomy_ordering_data.push( term_data ); 39 | }); 40 | 41 | // AJAX Data. 42 | const data = { 43 | 'action': 'yikes_sto_update_taxonomy_order', 44 | 'taxonomy_ordering_data': taxonomy_ordering_data, 45 | 'base_index': base_index, 46 | 'term_order_nonce': simple_taxonomy_ordering_data.term_order_nonce 47 | }; 48 | 49 | // Run the ajax request. 50 | $.ajax({ 51 | type: 'POST', 52 | url: window.ajaxurl, 53 | data: data, 54 | dataType: 'JSON', 55 | success: function() { 56 | $( '.yikes-simple-taxonomy-preloader' ).remove(); 57 | item.find( 'input[type="checkbox"]' ).show(); 58 | } 59 | }); 60 | } 61 | }); 62 | } 63 | }); 64 | })( jQuery ); 65 | -------------------------------------------------------------------------------- /lib/js/yikes-tax-drag-drop.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e(document).ready((function(){const t=parseInt(simple_taxonomy_ordering_data.paged)>0?(parseInt(simple_taxonomy_ordering_data.paged)-1)*parseInt(e("#"+simple_taxonomy_ordering_data.per_page_id).val()):0,a=e("#the-list");a.find("tr:first-child").hasClass("no-items")||a.sortable({placeholder:"yikes-drag-drop-tax-placeholder",axis:"y",start:function(t,a){const o=e(a.item[0]);e(".yikes-drag-drop-tax-placeholder").css("height",o.css("height")).css("display","flex").css("width","0")},update:function(o,r){const n=e(r.item[0]);n.find('input[type="checkbox"]').hide().after('');const i=[];a.find("tr.ui-sortable-handle").each((function(){const t=e(this),a={term_id:t.attr("id").replace("tag-",""),order:parseInt(t.index())+1};i.push(a)}));const s={action:"yikes_sto_update_taxonomy_order",taxonomy_ordering_data:i,base_index:t,term_order_nonce:simple_taxonomy_ordering_data.term_order_nonce};e.ajax({type:"POST",url:window.ajaxurl,data:s,dataType:"JSON",success:function(t){e(".yikes-simple-taxonomy-preloader").remove(),n.find('input[type="checkbox"]').show()}})}})}))}(jQuery); 2 | -------------------------------------------------------------------------------- /lib/options.php: -------------------------------------------------------------------------------- 1 | base ) && 'settings_page_yikes-simple-taxonomy-ordering' === $screen->base; 42 | } 43 | 44 | /** 45 | * Add additiona scripts and styles as needed. 46 | */ 47 | public function enqueue_assets() { 48 | if ( $this->is_settings_page() ) { 49 | $min = SCRIPT_DEBUG ? '' : '.min'; 50 | wp_enqueue_style( 'select2', YIKES_STO_URL . "lib/css/select2{$min}.css", array(), YIKES_STO_SELECT2_VERSION, 'all' ); 51 | wp_enqueue_script( 'select2', YIKES_STO_URL . "lib/js/select2{$min}.js", array( 'jquery' ), YIKES_STO_SELECT2_VERSION, true ); 52 | wp_add_inline_script( 'select2', 'jQuery( document ).ready(function() { jQuery( "#yikes-sto-select2" ).css( "width", "100%" ).select2(); });' ); 53 | } 54 | } 55 | 56 | /** 57 | * Filter the footer text and add custom text asking for review. 58 | */ 59 | public function footer_callout() { 60 | 61 | $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : ''; 62 | if ( $this->is_settings_page() ) { 63 | ?> 64 | 70 | 71 | Evan Herman', 76 | '' 77 | ); 78 | ?> 79 | 80 | options = get_option( YIKES_STO_OPTION_NAME, array() ); 104 | ?> 105 |
      106 |

      107 |
      108 | 114 |
      115 |
      116 | get_taxonomies(); 153 | $enabled = isset( $this->options['enabled_taxonomies'] ) ? array_flip( $this->options['enabled_taxonomies'] ) : array(); 154 | if ( $taxonomies ) { 155 | ?> 156 | 179 |

      180 | true, 198 | ) 199 | ); 200 | 201 | /** 202 | * Filter yikes_simple_taxonomy_ordering_ignored_taxonomies. 203 | * 204 | * Add or remove taxonomies that should not be available for ordering. 205 | * 206 | * @param array $excluded_taxonomies The array of ignored taxonomy slugs. 207 | * @param array $taxonomies The array of included taxonomy slugs. 208 | * 209 | * @return array $excluded_taxonomies The array of taxonomies that should be excluded from ordering. 210 | */ 211 | $excluded_taxonomies = apply_filters( 'yikes_simple_taxonomy_ordering_excluded_taxonomies', array(), $taxonomies ); 212 | 213 | // Remove excluded taxonomies. 214 | $taxonomies = array_diff( $taxonomies, $excluded_taxonomies ); 215 | 216 | /** 217 | * Filter yikes_simple_taxonomy_ordering_included_taxonomies. 218 | * 219 | * Add or remove taxonomies that are available for ordering. 220 | * 221 | * @param array $taxonomies The array of included taxonomy slugs. 222 | * @param array $excluded_taxonomies The array of ignored taxonomy slugs. 223 | * 224 | * @return array $excluded_taxonomies The array of taxonomies that should be excluded from ordering. 225 | */ 226 | $taxonomies = apply_filters( 'yikes_simple_taxonomy_ordering_included_taxonomies', $taxonomies, $excluded_taxonomies ); 227 | 228 | // Return the taxonomies. 229 | return $taxonomies; 230 | } 231 | 232 | } 233 | 234 | } 235 | 236 | new YIKES_Simple_Taxonomy_Options(); 237 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-taxonomy-ordering", 3 | "title": "Simple Taxonomy Ordering", 4 | "description": "This plugin offers a UI to enable/disable endpoints and meta data for CPTs and taxonomies using WordPress' REST API.", 5 | "version": "2.3.4", 6 | "tested_up_to": "6.0", 7 | "author": "Evan Herman", 8 | "license": "GPL-2.0", 9 | "repository": "EvanHerman/simple-taxonomy-ordering", 10 | "homepage": "https://wordpress.org/plugins/simple-taxonomy-ordering/", 11 | "bugs": { 12 | "url": "https://github.com/EvanHerman/yikes-inc-simple-taxonomy-ordering/issues" 13 | }, 14 | "scripts": { 15 | "build": "yarn min && rm -rf build/* && rsync -av --mkpath --exclude-from .distignore --delete . build/simple-taxonomy-ordering/ && cd build/ && zip -r simple-taxonomy-ordering.zip simple-taxonomy-ordering/.", 16 | "min": "yarn min:css && yarn min:js", 17 | "min:js": "minify ./lib/js/yikes-tax-drag-drop.js > ./lib/js/yikes-tax-drag-drop.min.js", 18 | "min:css": "minify ./lib/css/yikes-tax-drag-drop.css > ./lib/css/yikes-tax-drag-drop.min.css", 19 | "install:tests": ".dev/scripts/install-wp-tests.sh wordpress_test root password 127.0.0.1 latest", 20 | "test:php": "./vendor/bin/phpunit --coverage-text", 21 | "test:php-coverage": "./vendor/bin/phpunit --coverage-html .dev/tests/php/coverage/", 22 | "test:php-coverage-cli": "./vendor/bin/phpunit --coverage-clover=clover.xml --log-junit=junit.xml", 23 | "lint": "yarn lint:css && yarn lint:js", 24 | "lint:js": "yarn eslint 'lib/js/*.js'", 25 | "lint:css": "yarn stylelint lib/css/*.css", 26 | "phpcs": "./vendor/bin/phpcs .", 27 | "generate-pot": "wp i18n make-pot . languages/simple-taxonomy-ordering.pot --domain=simple-taxonomy-ordering --include=yikes-custom-taxonomy-order.php,lib/options.php --subtract-and-merge", 28 | "watch": "npm-watch", 29 | "prepare": "husky install", 30 | "version": "grunt version && yarn generate-pot && git add -A .", 31 | "postversion": "git push && git push --tags" 32 | }, 33 | "watch": { 34 | "min": { 35 | "patterns": [ 36 | "lib/js", 37 | "lib/css" 38 | ], 39 | "extensions": "js,css", 40 | "quiet": true, 41 | "runOnChangeOnly": true, 42 | "ignore": "*.min.*" 43 | } 44 | }, 45 | "devDependencies": { 46 | "eslint": "^8.17.0", 47 | "grunt": "^1.5.3", 48 | "grunt-text-replace": "^0.4.0", 49 | "husky": "^8.0.1", 50 | "minify": "^9.1.0", 51 | "npm-watch": "^0.11.0", 52 | "stylelint": "^14.9.1", 53 | "stylelint-config-standard": "^26.0.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Rules for Simple Taxonomy Ordering 4 | 5 | 6 | 7 | ./ 8 | 9 | build/* 10 | .dev/* 11 | vendor/* 12 | node_modules/* 13 | assets/* 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | warning 24 | 25 | 26 | 27 | 28 | warning 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | ./.dev/tests/php/ 12 | 13 | 14 | 15 | 16 | ./yikes-custom-taxonomy-order.php 17 | ./lib 18 | 19 | ./build 20 | ./node_modules 21 | ./vendor 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Simple Taxonomy Ordering === 2 | Contributors: yikesinc, eherman24, liljimmi, yikesitskevin, jpowersdev 3 | Tags: admin, term, meta, simple, order, taxonomy, metadata, termmeta, reorder 4 | Requires at least: 4.4 5 | Tested up to: 6.0 6 | Stable tag: 2.3.4 7 | 8 | Quickly and easily reorder taxonomy terms with an easy to use and intuitive drag and drop interface. 9 | 10 | == Description == 11 | 12 | Order all of the taxonomy terms on your site with a simple to use, intuitive drag and drop interface. The plugin works for WordPress core taxonomies -- Categories and Tags -- and any custom taxonomies you have created. 13 | 14 | Activate the plugin, enable your taxonomy on the settings page, and drag and drop the taxonomies into the desired position. It couldn't be easier. 15 | 16 | On the front end of the site your taxonomy terms will display in the order set in the dashboard. 17 | 18 | Requires WordPress 4.4 or later due to the use of the term meta. 19 | 20 | == Other Notes == 21 | 22 | **Query Usage** 23 | 24 | * If you're trying to query for taxonomy terms (e.g. using `WP_Query` or functions like `get_terms()`), and you'd like them to be returned in the order specified by the plugin, you need to add the tax_position parameter in your call. For example: `'meta_key' => 'tax_position'` and `'orderby' => 'tax_position'`. Thanks to @certainlyakey on GitHub for pointing this out. 25 | 26 | == Screenshots == 27 | 28 | 1. Simple Taxonomy Ordering settings page, allows you to specify which taxonomy you want to enable drag & drop ordering on. 29 | 30 | == Installation == 31 | 32 | * Unzip and upload contents to your plugins directory (usually wp-content/plugins/). 33 | * Activate the plugin. 34 | * Head to the settings page, 'Settings > Simple Taxonomy Ordering'. 35 | * Select the taxonomies you want to enable drag and drop ordering on. Save the settings. 36 | * Head to the taxonomy edit page and re-order the taxonomies as needed. 37 | * Profit 38 | 39 | == Changelog == 40 | 41 | = 2.3.4 = 42 | * Fixes custom order not being displayed on edit-tags pages. 43 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | query( "DELETE FROM $wpdb->termmeta WHERE meta_key = 'tax_position'" ); 23 | -------------------------------------------------------------------------------- /yikes-custom-taxonomy-order.php: -------------------------------------------------------------------------------- 1 | base && $this->is_taxonomy_ordering_enabled( $screen->taxonomy ) ) { 61 | $this->enqueue(); 62 | $this->default_term_order( $screen->taxonomy ); 63 | $this->yikes_sto_custom_help_tab(); 64 | 65 | add_filter( 'terms_clauses', array( $this, 'set_tax_order' ), 10, 3 ); 66 | } 67 | } 68 | 69 | /** 70 | * Add a help tab to the taxonomy screen. 71 | */ 72 | public function yikes_sto_custom_help_tab() { 73 | $screen = get_current_screen(); 74 | $taxonomy = function_exists( 'get_current_screen' ) ? get_current_screen()->taxonomy : ''; 75 | $options = get_option( YIKES_STO_OPTION_NAME, array() ); 76 | 77 | // Only show the help tab on enabled taxonomies. 78 | if ( empty( $taxonomy ) || empty( $options ) || ! isset( $options['enabled_taxonomies'] ) || ! in_array( $taxonomy, $options['enabled_taxonomies'], true ) ) { 79 | return; 80 | } 81 | 82 | $taxonomy = get_taxonomy( $taxonomy ); 83 | 84 | if ( ( ! isset( $taxonomy->labels ) || ! isset( $taxonomy->labels->singular_name ) ) && ! isset( $taxonomy->labels ) ) { 85 | return; 86 | } 87 | 88 | $taxonomy_label = ( isset( $taxonomy->labels ) && isset( $taxonomy->labels->singular_name ) ) ? $taxonomy->labels->singular_name : $taxonomy->label; 89 | 90 | $screen->add_help_tab( 91 | array( 92 | 'id' => 'yikes_sto_help_tab', 93 | 'title' => sprintf( 94 | /* translators: %s is the taxonomy singular name. eg: Category */ 95 | __( '%s Ordering', 'simple-taxonomy-ordering' ), 96 | esc_attr( $taxonomy_label ) 97 | ), 98 | 'content' => '

      ' . __( 'To reposition a taxonomy in the list, simply click on a taxonomy and drag & drop it into the desired position. Each time you reposition a taxonomy, the data will update in the database and on the front end of your site.', 'simple-taxonomy-ordering' ) . '

      ' . __( 'Example', 'simple-taxonomy-ordering' ) . ':

      ' . __( 'Simple Taxonomy Ordering Demo', 'simple-taxonomy-ordering' ) . '', 99 | ) 100 | ); 101 | } 102 | 103 | /** 104 | * Order the taxonomies on the front end. 105 | */ 106 | public function front_end_order_terms() { 107 | if ( ! is_admin() && apply_filters( 'yikes_simple_taxonomy_ordering_front_end_order_terms', true ) ) { 108 | add_filter( 'terms_clauses', array( $this, 'set_tax_order' ), 10, 3 ); 109 | } 110 | } 111 | 112 | /** 113 | * Enqueue assets. 114 | */ 115 | public function enqueue() { 116 | $min = SCRIPT_DEBUG ? '' : '.min'; 117 | $tax = function_exists( 'get_current_screen' ) ? get_current_screen()->taxonomy : ''; 118 | wp_enqueue_style( 'yikes-tax-drag-drop-styles', YIKES_STO_URL . "lib/css/yikes-tax-drag-drop{$min}.css", array(), YIKES_STO_VERSION, 'all' ); 119 | wp_enqueue_script( 'yikes-tax-drag-drop', YIKES_STO_URL . "lib/js/yikes-tax-drag-drop{$min}.js", array( 'jquery-ui-core', 'jquery-ui-sortable' ), YIKES_STO_VERSION, true ); 120 | wp_localize_script( 121 | 'yikes-tax-drag-drop', 122 | 'simple_taxonomy_ordering_data', 123 | array( 124 | 'preloader_url' => esc_url( admin_url( 'images/wpspin_light.gif' ) ), 125 | 'term_order_nonce' => wp_create_nonce( 'term_order_nonce' ), 126 | 'paged' => isset( $_GET['paged'] ) ? absint( wp_unslash( $_GET['paged'] ) ) : 0, 127 | 'per_page_id' => "edit_{$tax}_per_page", 128 | ) 129 | ); 130 | } 131 | 132 | /** 133 | * Default the taxonomy's terms' order if it's not set. 134 | * 135 | * @param string $tax_slug The taxonomy's slug. 136 | */ 137 | public function default_term_order( $tax_slug ) { 138 | $terms = get_terms( $tax_slug, array( 'hide_empty' => false ) ); 139 | $order = $this->get_max_taxonomy_order( $tax_slug ); 140 | foreach ( $terms as $term ) { 141 | if ( ! get_term_meta( $term->term_id, 'tax_position', true ) ) { 142 | update_term_meta( $term->term_id, 'tax_position', $order ); 143 | $order++; 144 | } 145 | } 146 | } 147 | 148 | /** 149 | * Get the maximum tax_position for this taxonomy. This will be applied to terms that don't have a tax position. 150 | * 151 | * @param string $tax_slug The taxonomy slug. 152 | */ 153 | private function get_max_taxonomy_order( $tax_slug ) { 154 | global $wpdb; 155 | $max_term_order = $wpdb->get_col( 156 | $wpdb->prepare( 157 | "SELECT MAX( CAST( tm.meta_value AS UNSIGNED ) ) 158 | FROM $wpdb->terms t 159 | JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id AND tt.taxonomy = '%s' 160 | JOIN $wpdb->termmeta tm ON tm.term_id = t.term_id WHERE tm.meta_key = 'tax_position'", 161 | $tax_slug 162 | ) 163 | ); 164 | $max_term_order = is_array( $max_term_order ) ? current( $max_term_order ) : 0; 165 | return (int) 0 === $max_term_order || empty( $max_term_order ) ? 1 : (int) $max_term_order + 1; 166 | } 167 | 168 | /** 169 | * Re-Order the taxonomies based on the tax_position value. 170 | * 171 | * @param array $pieces Array of SQL query clauses. 172 | * @param array $taxonomies Array of taxonomy names. 173 | */ 174 | public function set_tax_order( $pieces, $taxonomies ) { 175 | foreach ( $taxonomies as $taxonomy ) { 176 | if ( $this->is_taxonomy_ordering_enabled( $taxonomy ) ) { 177 | global $wpdb; 178 | 179 | $join_statement = " LEFT JOIN $wpdb->termmeta AS term_meta ON t.term_id = term_meta.term_id AND term_meta.meta_key = 'tax_position'"; 180 | 181 | if ( ! $this->does_substring_exist( $pieces['join'], $join_statement ) ) { 182 | $pieces['join'] .= $join_statement; 183 | } 184 | $pieces['orderby'] = 'ORDER BY CAST( term_meta.meta_value AS UNSIGNED )'; 185 | } 186 | } 187 | return $pieces; 188 | } 189 | 190 | /** 191 | * Check if a substring exists inside a string. 192 | * 193 | * @param string $string The main string (haystack) we're searching in. 194 | * @param string $substring The substring we're searching for. 195 | * 196 | * @return bool True if substring exists, else false. 197 | */ 198 | protected function does_substring_exist( $string, $substring ) { 199 | return strstr( $string, $substring ) !== false; 200 | } 201 | 202 | /** 203 | * AJAX Handler to update terms' tax position. 204 | */ 205 | public function update_taxonomy_order() { 206 | if ( ! check_ajax_referer( 'term_order_nonce', 'term_order_nonce', false ) ) { 207 | wp_send_json_error(); 208 | } 209 | 210 | $taxonomy_ordering_data = filter_input( INPUT_POST, 'taxonomy_ordering_data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); 211 | $base_index = filter_input( INPUT_POST, 'base_index', FILTER_SANITIZE_NUMBER_INT ); 212 | 213 | foreach ( $taxonomy_ordering_data as $order_data ) { 214 | 215 | // Due to the way WordPress shows parent categories on multiple pages, we need to check if the parent category's position should be updated. 216 | // If the category's current position is less than the base index (i.e. the category shouldn't be on this page), then don't update it. 217 | if ( $base_index > 0 ) { 218 | $current_position = get_term_meta( $order_data['term_id'], 'tax_position', true ); 219 | if ( (int) $current_position < (int) $base_index ) { 220 | continue; 221 | } 222 | } 223 | 224 | update_term_meta( $order_data['term_id'], 'tax_position', ( (int) $order_data['order'] + (int) $base_index ) ); 225 | 226 | } 227 | 228 | do_action( 'yikes_sto_taxonomy_order_updated', $taxonomy_ordering_data, $base_index ); 229 | 230 | wp_send_json_success(); 231 | } 232 | 233 | /** 234 | * Is Taxonomy Ordering Enabled. 235 | * 236 | * @param string $tax_slug the taxnomies slug. 237 | */ 238 | public function is_taxonomy_ordering_enabled( $tax_slug ) { 239 | $option_default = array( 'enabled_taxonomies' => array() ); 240 | $option = get_option( YIKES_STO_OPTION_NAME, $option_default ); 241 | $enabled_taxonomies = array_flip( $option['enabled_taxonomies'] ); 242 | 243 | return isset( $enabled_taxonomies[ $tax_slug ] ); 244 | } 245 | 246 | /** 247 | * Internationalization. 248 | */ 249 | public function load_plugin_textdomain() { 250 | load_plugin_textdomain( 251 | 'simple-taxonomy-ordering', 252 | false, 253 | YIKES_STO_PATH . 'languages/' 254 | ); 255 | } 256 | } 257 | } 258 | 259 | new Yikes_Custom_Taxonomy_Order(); 260 | --------------------------------------------------------------------------------