@kamranbaylarov/one-select
v1.1.0
Published
A powerful, flexible, and feature-rich multi-select dropdown component for jQuery
Maintainers
Readme
🎯 OneSelect - jQuery Multi-Select Dropdown Component
Version: 1.2.0 | Author: Kamran Baylarov
A powerful, flexible, and feature-rich multi-select dropdown component for jQuery.
📋 Table of Contents
- Overview
- Features
- Installation
- All Parameters
- Data Attributes
- Methods
- Callbacks
- Examples
- AJAX Integration
- Form Submission
- Badge System
- CSS Styling
🎯 Overview
OneSelect is a powerful jQuery-based plugin that provides multi-select functionality with comprehensive customization options.
🚀 Key Features
- ✅ Multiple Selection - Select multiple items with checkboxes
- 🎯 Select All - Select all items with one click
- 🏷️️ Badge System - Display selected items as badges
- 📤 External Badges - Display badges in external elements
- 🔄 AJAX Support - Load data dynamically
- 🔍 Search Feature - Local filtering or AJAX search with debounce
- 📝 Form Submission - Submit data via hidden inputs
- 🎨 Fully Customizable - Complete control with 27+ parameters
- 📱 Responsive - Works on all devices
- 🌐 Data Attributes - Configure via HTML attributes
- 🎪 Multiple Instances - Independent selects on same page
- 🌪 Click Outside - Close dropdown when clicking outside (default: true)
- 📍 Smart Positioning - Dropdown positioned with
position: fixedusing viewport coordinates - 🔀 Horizontal Scroll Detection - Automatically closes on any horizontal scroll to prevent misalignment
💡 Features
📊 Technical Stack
| Component | Technology |
|-----------|------------|
| Library | jQuery (required dependency) |
| Plugin Type | jQuery Plugin |
| Files | one-select.js, one-select.min.css |
🎯 Functionality
📦 Data Structures:
├── String Array: ['Apple', 'Banana', 'Cherry']
└── Object Array: [{id: 1, name: 'Apple'}, ...]
🎮 Interactions:
├── Click to select (checkbox)
├── "Select All" option
├── OK button (confirm)
├── Cancel button (clears selection and closes)
└── × button (remove from badges)
📤 Data Flow:
├── onChange(values, labels) - When selection changes
├── onOk(values, labels) - When OK clicked
├── onCancel() - When Cancel clicked
└── AJAX callbacks (beforeLoad, afterLoad, onLoadError)📦 Installation
Via NPM (Recommended)
npm install @kamranbaylarov/one-selectManual Download
Download from GitHub Releases
Dependencies
<!-- jQuery must be included first -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>Include Files
NPM:
<!-- CSS -->
<link rel="stylesheet" href="/node_modules/@kamranbaylarov/one-select/css/one-select.min.css">
<!-- JavaScript -->
<script src="/node_modules/@kamranbaylarov/one-select/js/one-select.min.js"></script>Manual:
<!-- CSS -->
<link rel="stylesheet" href="/path/to/one-select.min.css">
<!-- JavaScript -->
<script src="/path/to/one-select.js"></script>Create HTML Element
<div id="mySelect"></div>Initialize
$('#mySelect').oneSelect({
data: ['Apple', 'Banana', 'Cherry']
});⚙️ All Parameters
| Parameter | Type | Default | Description |
|---------|-----|---------|-------------|
| placeholder | String | 'Select options...' | Placeholder text when nothing selected |
| selectAllText | String | 'Select All' | "Select All" button text |
| okText | String | 'OK' | OK button text |
| cancelText | String | 'Cancel' | Cancel button text |
| data | Array | [] | Options list (string array only) |
| value | Number/Array/null | null | Single index or array of indices to pre-select |
| showCheckbox | Boolean | true | Show/hide checkboxes |
| showBadges | Boolean | false | Show badges in trigger |
| showBadgesExternal | String/null | null | External element ID (for badges) |
| showSearch | Boolean | false | Show search input in dropdown |
| searchPlaceholder | String | 'Search...' | Search input placeholder text |
| searchUrl | String/null | null | URL for AJAX search (GET request with q parameter) |
| searchDebounceDelay | Number | 300 | Delay in milliseconds for search debounce |
| closeOnScroll | Boolean | false | Close dropdown on page scroll |
| closeOnOutside | Boolean | true | Close dropdown when clicking outside |
| submitForm | Boolean | false | Submit form on OK click |
| submitOnOutside | Boolean | false | Submit form on outside click |
| formId | String/null | null | Specific form ID (null: parent form) |
| name | String/null | null | Hidden input name attribute |
| multiple | Boolean | true | Submit as array (name[]) |
| ajax | Object/null | null | AJAX configuration object |
| autoLoad | Boolean | true | Auto load data via AJAX |
| beforeLoad | Function/null | null | Called before AJAX |
| afterLoad | Function/null | null | Called after AJAX success |
| onLoadError | Function/null | null | Called on AJAX error |
| onChange | Function/null | null | Called when selection changes |
| onSelect | Function/null | null | Previous version of onChange |
| onOk | Function/null | null | Called when OK clicked |
| onCancel | Function/null | null | Called when Cancel clicked |
🏷️ Data Attributes
All parameters can be set via HTML data attributes. Data attributes override JS parameters.
| Data Attribute | Parameter | Type | Example |
|----------------|----------|-----|---------|
| data-ones-placeholder | placeholder | String | data-ones-placeholder="Select..." |
| data-ones-select-all-text | selectAllText | String | data-ones-select-all-text="Select All" |
| data-ones-ok-text | okText | String | data-ones-ok-text="Confirm" |
| data-ones-cancel-text | cancelText | String | data-ones-cancel-text="Cancel" |
| data-ones-data | data | Array | data-ones-data='["A","B","C"]' |
| data-ones-value | value | Number/Array | data-ones-value='"0"' or data-ones-value='["0","2"]' |
| data-ones-name | name | String | data-ones-name="items" |
| data-ones-multiple | multiple | Boolean | data-ones-multiple="true" |
| data-ones-show-checkbox | showCheckbox | Boolean | data-ones-show-checkbox="false" |
| data-ones-show-badges | showBadges | Boolean | data-ones-show-badges="true" |
| data-ones-show-badges-external | showBadgesExternal | String | data-ones-show-badges-external="badgesDiv" |
| data-ones-show-search | showSearch | Boolean | data-ones-show-search="true" |
| data-ones-search-placeholder | searchPlaceholder | String | data-ones-search-placeholder="Search items..." |
| data-ones-search-url | searchUrl | String | data-ones-search-url="/api/search" |
| data-ones-search-debounce-delay | searchDebounceDelay | Number | data-ones-search-debounce-delay="500" |
| data-ones-close-on-scroll | closeOnScroll | Boolean | data-ones-close-on-scroll="true" |
| data-ones-close-on-outside | closeOnOutside | Boolean | data-ones-close-on-outside="true" |
| data-ones-submit-form | submitForm | Boolean | data-ones-submit-form="true" |
| data-ones-submit-on-outside | submitOnOutside | Boolean | data-ones-submit-on-outside="true" |
| data-ones-form-id | formId | String | data-ones-form-id="myForm" |
| data-ones-auto-load | autoLoad | Boolean | data-ones-auto-load="false" |
| data-ones-ajax | ajax | Object | data-ones-ajax='{"url": "/api/items"}' |
Example:
<div id="mySelect"
data-ones-placeholder="Select products..."
data-ones-data='["Apple", "Banana", "Cherry"]'
data-ones-show-badges="true"
data-ones-name="fruits"
></div>
<script>
$('#mySelect').oneSelect({
// JS options (data attributes override these)
});
</script>🔧 Methods
Call via jQuery plugin method:
// Get selected values
var values = $('#mySelect').oneSelect('getValues');
var labels = $('#mySelect').oneSelect('getLabels');
// Set selection
$('#mySelect').oneSelect('value', ['Apple', 'Banana']);
// Update data
$('#mySelect').oneSelect('updateData', ['New', 'Data']);
// Load data via AJAX
$('#mySelect').oneSelect('loadData');
// Selection control
$('#mySelect').oneSelect('selectAll');
$('#mySelect').oneSelect('unselectAll');
$('#mySelect').oneSelect('select', 'Apple');
$('#mySelect').oneSelect('unselect', 'Banana');
$('#mySelect').oneSelect('toggleSelection', 'Cherry');
// Dropdown control
$('#mySelect').oneSelect('open');
$('#mySelect').oneSelect('close');
// Get instance ID
var instanceId = $('#mySelect').oneSelect('getInstanceId');
// Get instance object
var instance = OneSelect.getInstance(instanceId);
// Get all instances
var allInstances = OneSelect.getAllInstances();
// Destroy
$('#mySelect').oneSelect('destroy');🎯 Callbacks
onChange(values, labels)
Called every time selection changes. Most important callback.
$('#mySelect').oneSelect({
data: ['A', 'B', 'C'],
onChange: function(values, labels) {
console.log('Values:', values);
console.log('Labels:', labels);
// values: ['A', 'C']
// labels: ['A', 'C']
}
});onOk(values, labels)
Called when OK button is clicked.
$('#mySelect').oneSelect({
onOk: function(values, labels) {
alert('Selected: ' + labels.join(', '));
}
});onCancel()
Called when Cancel button is clicked and clears all selections.
$('#mySelect').oneSelect({
onCancel: function() {
console.log('Selection cancelled');
}
});AJAX Callbacks
$('#mySelect').oneSelect({
ajax: {
url: '/api/items',
method: 'GET'
},
beforeLoad: function() {
$('#loading').show();
},
afterLoad: function(response) {
$('#loading').hide();
console.log('Data loaded:', response);
},
onLoadError: function(error) {
$('#error').text('Error: ' + error);
}
});📚 Examples
1. Basic Usage
$('#mySelect').oneSelect({
placeholder: 'Select fruits...',
data: ['Apple', 'Banana', 'Cherry', 'Mango']
});2. How It Works
Data Format: String array only
data: ['Apple', 'Banana', 'Cherry']Result:
- value (what gets submitted):
0, 1, 2(array indices) - label (what user sees):
'Apple', 'Banana', 'Cherry'
Perfect for:
- PHP associative arrays converted to indexed arrays
- Backend IDs as array indices
- Display values as array elements
Example with PHP data:
// PHP
$items = [
5 => "M.Hadi_9_6/1",
6 => "Sarayevo_20_4/2/1",
7 => "Sarayevo_13B_3/2/1"
];
echo json_encode(array_values($items));
// Output: ["M.Hadi_9_6/1","Sarayevo_20_4/2/1","Sarayevo_13B_3/2/1"]// JavaScript
$('#mySelect').oneSelect({
data: ["M.Hadi_9_6/1", "Sarayevo_20_4/2/1", "Sarayevo_13B_3/2/1"]
});
// value: 0, 1, 2 (array indices)
// label: "M.Hadi_9_6/1", "Sarayevo_20_4/2/1", "Sarayevo_13B_3/2/1"3. Value Parameter (Pre-selected Items)
// Single value (by index)
$('#mySelect').oneSelect({
data: ['Apple', 'Banana', 'Cherry', 'Mango'],
value: 0 // Index 0 ('Apple') will be selected
});
// Array with multiple selection
$('#mySelect').oneSelect({
data: ['Apple', 'Banana', 'Cherry', 'Mango'],
value: [0, 2], // Indices 0 ('Apple') and 2 ('Cherry') will be selected
showBadges: true
});
// HTML data attribute
<div class="one-select"
data-ones-data='["Apple", "Banana", "Cherry"]'
data-ones-value='"0"'> <!-- Single index -->
</div>
<!-- OR -->
<div class="one-select"
data-ones-data='["Apple", "Banana", "Cherry"]'
data-ones-value='["0", "2"]'> <!-- Multiple indices -->
</div>4. Badge System
// Trigger badges
$('#mySelect').oneSelect({
data: ['A', 'B', 'C'],
showBadges: true
});
// External badges
<div id="badgesContainer"></div>
$('#mySelect').oneSelect({
data: ['A', 'B', 'C'],
showBadgesExternal: 'badgesContainer'
});5. Form Submission
$('#mySelect').oneSelect({
data: ['Item 1', 'Item 2'],
name: 'items',
multiple: true,
submitForm: true,
formId: 'myForm'
});Backend example:
// Receive items array: [0, 1] (indices of selected items)
// Use indices to get original values from your data array6. AJAX Data Loading
$('#mySelect').oneSelect({
ajax: {
url: '/api/categories',
method: 'GET'
},
beforeLoad: function() {
console.log('Loading...');
},
afterLoad: function(response) {
console.log('Loaded:', response);
}
});7. Multiple Instances
// Each has independent ID
var fruits = $('#fruits').oneSelect({
data: ['Apple', 'Banana', 'Cherry']
});
var colors = $('#colors').oneSelect({
data: ['Red', 'Blue', 'Green']
});
// External control over instances
var fruitsInstance = OneSelect.getInstance(
$('#fruits').oneSelect('getInstanceId')
);
fruitsInstance.selectAll();8. Search Feature
// Enable local search (filters existing data)
$('#mySelect').oneSelect({
data: ['Apple', 'Banana', 'Cherry', 'Mango', 'Orange', 'Grape'],
showSearch: true,
searchPlaceholder: 'Type to search...'
});
// Enable AJAX search (with debounce)
$('#mySelect').oneSelect({
showSearch: true,
searchUrl: '/api/search',
searchDebounceDelay: 500,
searchPlaceholder: 'Search items...'
});
// HTML data attribute example (local search)
<div class="one-select"
data-ones-data='["Apple", "Banana", "Cherry", "Mango"]'
data-ones-show-search="true"
data-ones-search-placeholder="Find a fruit...">
</div>
// HTML data attribute example (AJAX search)
<div class="one-select"
data-ones-show-search="true"
data-ones-search-url="/api/customers/search"
data-ones-search-debounce-delay="300"
data-ones-search-placeholder="Search customers...">
</div>AJAX Search Server Response Format:
The server should respond with JSON in one of these formats:
// Direct array
["Apple", "Banana", "Cherry"]
// Wrapped with 'data'
{
"data": [{"value": 1, "label": "Apple"}, {"value": 2, "label": "Banana"}]
}
// Wrapped with 'results'
{
"results": ["Apple", "Banana"]
}The request will be sent as GET /api/search?q=searchterm
📦 Horizontal Scroll Behavior
Automatic dropdown closing on horizontal scroll:
The dropdown automatically closes when the user performs any horizontal scrolling action while the dropdown is open. This prevents the dropdown from appearing in the wrong position when:
- Tables with
overflow-x: autoare scrolled horizontally - Any scrollable container is scrolled horizontally
- Touchpad/trackpad horizontal gestures are used
- Mouse wheel horizontal scrolling is performed
How It Works
The plugin uses two methods to detect horizontal scroll:
- Wheel Event Detection: Detects horizontal mouse/touchpad scrolling in real-time
- Periodic Scroll Checking: Every 50ms, checks if any scrollable element's
scrollLeftposition has changed
When horizontal scroll is detected, the dropdown immediately closes.
Example
<div style="overflow-x: auto; width: 100%;">
<table style="width: 2000px;">
<tr>
<td>
<div id="mySelect"></div>
</td>
<td>Other columns...</td>
</tr>
</table>
</div>
<script>
$('#mySelect').oneSelect({
data: ['Apple', 'Banana', 'Cherry']
});
</script>Behavior:
- User opens dropdown ✅
- User scrolls table horizontally → Dropdown closes automatically ✅
🔄 AJAX Integration
AJAX Configuration
$('#mySelect').oneSelect({
ajax: {
url: '/api/items',
method: 'GET',
data: { category: 'fruits', active: true }
},
autoLoad: false
});
// Manual load
$('#loadBtn').on('click', function() {
$('#mySelect').oneSelect('loadData', {
url: '/api/different-items',
data: { filter: 'active' }
});
});Supported Response Formats
1. Direct array:
["Apple", "Banana", "Cherry"]2. Wrapped with 'data':
{
"data": ["Apple", "Banana"]
}3. Wrapped with 'results':
{
"results": ["Apple", "Banana"]
}4. Object array:
[
{"value": 1, "label": "Apple"},
{"value": 2, "label": "Banana"}
]📝 Form Submission
Hidden Inputs
Component automatically creates <input type="hidden"> elements:
$('#mySelect').oneSelect({
name: 'items',
multiple: true,
data: ['A', 'B', 'C']
});HTML result:
<input type="hidden" name="items[]" value="A">
<input type="hidden" name="items[]" value="B">
<input type="hidden" name="items[]" value="C">🏷️ Badge System
Trigger Badges
$('#mySelect').oneSelect({
showBadges: true
});Result: [Apple ×] [Banana ×] [Cherry ×]
External Badges
<div id="myBadges"></div>
$('#mySelect').oneSelect({
showBadgesExternal: 'myBadges'
});Badge Properties
- Background:
#3b82f6(light blue) - Text color:
#fff(white) - Remove button (×):
#fff(white) - Hover: Light gray background
- Remove: Clicking × button unselects item
Both Together
$('#mySelect').oneSelect({
showBadges: true, // Badge in trigger
showBadgesExternal: 'myBadges' // Badge outside as well
});🎨 CSS Styling
Main CSS classes with cms- prefix:
.one-select /* Main container (relative positioned) */
.cms-wrapper /* Wrapper (relative positioned) */
.cms-trigger /* Button that opens dropdown */
.cms-selected-text /* Selected text */
.cms-dropdown /* Dropdown menu (absolute positioned) */
.cms-search-wrapper /* Search input wrapper */
.cms-search-input /* Search input field */
.cms-options-container /* Options container */
.cms-options-container.cms-loading /* Loading state for AJAX search */
.cms-option /* Single option */
.cms-option.selected /* Selected option */
.cms-option.select-all /* "Select All" option */
.cms-badge /* Badge */
.cms-badge-remove /* Badge × button */
.cms-btn /* OK/Cancel buttons */DOM Structure
<!-- Wrapper element (your container) -->
<div class="one-select">
<div class="cms-wrapper">
<div class="cms-trigger">
<span class="cms-selected-text">Select...</span>
</div>
</div>
</div>
<!-- Dropdown is appended to body with dynamic positioning -->
<div class="cms-dropdown" style="position: fixed; top: ...; left: ...; width: ...;">
<!-- Search input (when showSearch is true) -->
<div class="cms-search-wrapper">
<input type="text" class="cms-search-input" placeholder="Search...">
</div>
<div class="cms-options-container">
<div class="cms-option select-all">...</div>
<div class="cms-option">...</div>
</div>
<div class="cms-buttons">
<button class="cms-btn cms-btn-ok">OK</button>
<button class="cms-btn cms-btn-cancel">Cancel</button>
</div>
</div>Note: The dropdown is positioned using position: fixed with viewport coordinates (getBoundingClientRect()). This ensures it stays correctly positioned even when parent elements scroll.
Custom CSS Example
/* Selected option styling */
.cms-option.selected label {
font-weight: 600;
color: #007bff;
}
/* Badge styling */
.cms-badge {
background: #3b82f6;
color: #fff;
border-radius: 12px;
padding: 3px 8px;
}
/* Search input styling */
.cms-search-input {
background: #f8f9fa;
border-color: #dee2e6;
}
.cms-search-input:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
}
/* Custom dropdown width */
.one-select {
width: 400px;
}🚀 Quick Usage Examples
// 1. Simple
$('#select1').oneSelect({
data: ['A', 'B', 'C']
});
// 2. Pre-selected items (by index)
$('#select2').oneSelect({
data: ['Apple', 'Banana', 'Cherry'],
value: [0, 2] // Selects indices 0 and 2
});
// 3. Badges
$('#select3').oneSelect({
data: ['X', 'Y', 'Z'],
showBadges: true
});
// 4. Form submission
$('#select4').oneSelect({
data: ['P1', 'P2'],
name: 'products',
multiple: true,
submitForm: true,
formId: 'myForm'
});
// 5. AJAX
$('#select5').oneSelect({
ajax: {url: '/api/items'},
autoLoad: false
});
// 6. Click outside behavior
$('#select6').oneSelect({
closeOnOutside: true // Close when clicking outside (default)
});
// 7. Search feature (local filtering)
$('#select7').oneSelect({
data: ['Apple', 'Banana', 'Cherry', 'Mango', 'Orange'],
showSearch: true,
searchPlaceholder: 'Search fruits...'
});
// 8. AJAX search with debounce
$('#select8').oneSelect({
showSearch: true,
searchUrl: '/api/search',
searchDebounceDelay: 500
});📞 Support
Links
- NPM Package: @kamranbaylarov/one-select
- GitHub: KamranBeylarov/one-select
- Issues: Report issues
Installation
# NPM
npm install @kamranbaylarov/one-select
# CDN (coming soon)Project Structure
one-select/
├── css/
│ └── one-select.min.css
├── js/
│ ├── one-select.js
│ └── one-select.min.js
├── package.json
└── README.mdLicense
MIT License - Feel free to use in your projects!
🎯 Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Opera (latest)
OneSelect makes multi-select dropdowns simple and powerful! 🚀
