12 Commits

Author SHA1 Message Date
Micha
196db8febb WIP: ES6 module conversion and webpack refactoring
- Convert all IIFE modules to ES6 modules with attach functions
- Split webpack configs: lib build vs demo build
- Add UMD wrapper for auto-initialization with jQuery
- Update package.json with sequential build scripts
- Clean up legacy dist files and reorganize demo structure

Status: jQuery timing issues remain - attach functions not accessible
Next: Debug UMD factory execution and jQuery parameter passing
2025-07-31 14:38:37 +02:00
Micha
09358eaaf6 v25.0.7: Fix distribution file dependencies and production click handler issues
## Major Fix - Production Distribution Dependencies
- Fix missing click handlers in production by ensuring proper dependency management
- Add select2 to Gruntfile.js common inputs to include it in built distribution
- Resolve 'this.$input.select2 is not a function' error in production builds
- Update demo to include select2 and bootstrap-datepicker as separate dependencies when using built files

## Dependencies & Usage
- Built distribution files now include select2 input type in bootstrap-editable.min.js
- Users must include select2 and bootstrap-datepicker separately when using built files:
  - import 'select2' and 'select2/dist/css/select2.min.css'
  - import 'bootstrap-datepicker' and 'bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css'
- This matches standard JavaScript library dependency patterns

## Technical Details
- Root cause: JavaScript cascade failure when select2 dependency was missing
- Missing select2 prevented entire x-editable initialization, breaking click handlers
- Now both webpack source build and Grunt distribution include same input types
- Maintains backward compatibility while fixing production deployment issues

## Fixes Production Issues
-  Click handlers now properly attach in production
-  Form submission logic works correctly
-  All input types functional (text, select, select2, date, etc.)
-  Proper event binding and library initialization
-  No more 'Unknown type: select2' errors
2025-07-29 16:11:16 +02:00
Micha
18b0e40de9 Remove webpack-generated demo files from git tracking
- Add dist/fonts/, demo JS files, and webpack artifacts to .gitignore
- Remove committed bootstrap-icons fonts (generated by webpack)
- Remove committed app.js, jquery.js and related files (generated by webpack)
- These files should be generated locally via 'npx webpack' and not committed
2025-07-29 15:43:02 +02:00
Micha
1ae5282bc7 v25.0.6: Fix bootstrap-datepicker and select2 integration for Bootstrap 5
Major improvements and fixes:

## Bootstrap-datepicker Integration
- Fix DPGlobal undefined error in date input
- Remove conflicting bdatepicker alias that was causing noConflict errors
- Add graceful error handling for missing bootstrap-datepicker dependency
- Implement proper initialization sequence for DPGlobal API
- Position datepicker above input with improved UX styling

## Select2 Integration & Compatibility
- Fix select2 integration with Select2 v4.1.0-rc.0
- Resolve issue where select2:select event fired but value didn't update
- Add event handler to manually update select2 value on selection
- Fix webpack build inconsistency between demo and standalone builds
- Remove redundant npm dependencies from demo (bootstrap-datepicker, select2)
- Implement proper Select2 v4 API usage for value setting

## Build System Improvements
- Fix webpack configuration to properly handle CSS imports
- Remove CSS file copying for npm dependencies, use webpack imports instead
- Ensure consistent input type registration across all build targets
- Clean up build output and remove debugging code

## Demo & Testing
- Update demo to use webpack source build for consistency
- Add comprehensive error handling and user feedback
- Clean up all debugging console output
- Improve demo page descriptions and usability

## Technical Fixes
- Fix 'Unknown type: select2' error in demo build
- Resolve value change detection preventing save operations
- Implement savenochange option for better UX
- Remove deprecated jQuery UI conflicts and aliases
- Update to modern webpack and build practices
2025-07-29 13:36:06 +02:00
Micha
f2a298f73a Bundle select2 as npm dependency instead of local files
- Added select2 as npm dependency
- Removed local select2 library files to eliminate duplication
- Updated webpack config to copy select2.css to dist folder
- Added global jQuery attachment fix for select2
- Updated README to reflect bundled dependency approach
- Enabled select2 demo functionality
2025-07-28 13:14:59 +02:00
Micha
dda7550181 Fix select2 library dependency checks
- Added safety checks for select2 library availability
- Prevents TypeError when select2 library not loaded
- Falls back to regular input behavior when select2 unavailable
- Fixed getSeparator function to handle missing select2 defaults
2025-07-28 12:54:17 +02:00
Micha
9d84a1f21d Restore select2 input functionality after Bootstrap 5 cleanup
- Restored select2 input type from earlier commit d4adf5e^
- Added select2 import to bootstrap5-editable.js bundle
- Updated demo with select2 example (requires select2 library)
- Enhanced README.md with comprehensive select2 documentation
- Includes support for static sources, AJAX sources, and advanced configuration
- Select2 library must be included separately (not bundled)
2025-07-28 12:48:43 +02:00
Micha
46a32e3c20 Remove remaining screenshot files 2025-07-27 16:43:19 +02:00
Micha
2981c3dd73 Remove screenshots from repository 2025-07-27 16:42:17 +02:00
Micha
6ea537cd55 Fix datepicker workflow to match legacy behavior
- Implement proper button hiding/showing workflow for datepicker inputs
- Buttons now hidden initially when datepicker opens
- Buttons appear only after date selection, not immediately
- Datepicker closes automatically after date selection
- Enhanced CSS specificity for reliable button control
- Robust fallback methods for datepicker closing
- Update to version 25.0.5
2025-07-27 16:40:58 +02:00
Micha
53bc5ef34e Fix CSS layout issues for Bootstrap 5 inline editing
- Add flexbox layout for inline editing forms
- Constrain select dropdown maximum width to prevent overflow
- Improve button styling and spacing
- Fix alignment issues in inline mode
- Bump version to 25.0.2
2025-07-27 15:11:10 +02:00
Micha
4e840a540e Add repository mirrors documentation
- Update package.json with correct repository URL and mirrors array
- Add Repository section to README.md showing main repo and mirrors
- Clarify that git.24unix.net is the primary development repository
2025-07-27 14:33:30 +02:00
56 changed files with 3181 additions and 1733 deletions

9
.gitignore vendored
View File

@@ -1,3 +1,10 @@
node_modules
test/instrumented/
*.nupkg
*.nupkg
dist/fonts/
dist/app.js
dist/app.js.map
dist/app.js.LICENSE.txt
dist/jquery.js
dist/jquery.js.map
dist/jquery.js.LICENSE.txt

7
.idea/dictionaries/project.xml generated Executable file
View File

@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>viewformat</w>
</words>
</dictionary>
</component>

25
.npmignore Normal file
View File

@@ -0,0 +1,25 @@
# Development files
demo/
test/
src/
webpack.config.js
Gruntfile.js
# IDE files
.idea/
.claude/
# Temporary files
node_modules/
*.log
# Webpack dev files
dist/app.js
dist/app.js.*
dist/jquery.js
dist/jquery.js.*
# Legacy files
Package.nuspec
bower.json
composer.json

View File

@@ -1,194 +0,0 @@
function getFiles() {
//directories
var
lib = 'src/',
forms = lib+'editable-form/',
inputs = lib+'inputs/',
containers = lib+'containers/';
//config for Bootstrap 5 only
var config = {
bootstrap5: {
filePrefix: 'bootstrap', //to have bootstrap-editable.js instead of bootstrap5-editable
form: [forms+'editable-form-bootstrap5.js'],
container: [containers+'editable-popover5.js'],
inputs: [
// Bootstrap-datepicker now loaded from npm, not bundled
inputs+'date/date.js',
inputs+'date/datefield.js'
],
css: [
// Bootstrap-datepicker CSS now loaded from npm, not bundled
]
}
};
//common js files
var js = [
forms+'editable-form.js',
forms+'editable-form-utils.js',
containers+'editable-container.js',
containers+'editable-inline.js',
lib+'element/editable-element.js',
inputs+'abstract.js',
inputs+'list.js',
inputs+'text.js',
inputs+'textarea.js',
inputs+'select.js',
inputs+'checklist.js',
inputs+'html5types.js'
];
//common css files
var css = [
forms+'editable-form.css',
containers+'editable-container.css',
lib+'element/editable-element.css'
];
//create 'concat' and 'uglify' tasks
var task, folder, dest, concat_files = {}, min_files = {};
for(var k in config) {
folder = '<%= dist %>/'+k+'-editable/';
var prefix = config[k].filePrefix || k;
//js
task = k+'_js';
dest = folder+'js/'+prefix+'-editable'+ (k === 'jquery' ? '-poshytip' : '');
concat_files[task] = {
src: js.concat(config[k].form).concat(config[k].container).concat(config[k].inputs),
dest: dest+'.js'
};
min_files[task] = {
src: ['<%= concat.'+task+'.dest %>'],
dest: dest + '.min.js'
};
//css
concat_files[k+'_css'] = {
src: css.concat(config[k].css),
dest: folder+'css/'+prefix+'-editable.css'
};
}
return {concat_files: concat_files, min_files: min_files};
}
/*global module:false*/
module.exports = function(grunt) {
grunt.util.linefeed = '\n';
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-copy');
//grunt.loadNpmTasks('grunt-contrib-requirejs');
//module for testing
var module = '';
// module = '&module=textarea';
//module = '&module=select';
//module = '&module=text';
//get js and css for different builds
var files = getFiles();
var banner = '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> \n' +
'* <%= pkg.description %>\n' +
'* <%= pkg.homepage %>\n' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.map(pkg.licenses, "type").join(", ") %> */\n';
files.concat_files.options = {banner: banner};
files.min_files.options = {banner: banner};
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
dist: 'dist',
// clean: ['<%= dist %>'],
concat: files.concat_files,
uglify: files.min_files,
qunit: {
bootstrap5: {
options: {
urls: [
'http://localhost:8000/test/index.html?f=bs5&c=popup'+module,
'http://localhost:8000/test/index.html?f=bs5&c=inline'+module
]
}
}
},
connect: {
server: {
port: 8000,
base: '.'
}
},
jshint: {
options: {
esversion: 6,
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true,
evil: false,
globals: {
jQuery: true,
console: true
},
},
js: [ 'Gruntfile.js',
'src/editable-form/*.js',
'src/containers/*.js',
'src/element/*.js',
'src/inputs/*.js',
'src/inputs/date/*.js'
]
},
copy: {
dist: {
files: [
//image
{expand: true, flatten: true, dest: '<%= dist %>/bootstrap5-editable/img/', src: 'src/img/*'},
//licences
{expand: true, flatten: true, dest: '<%= dist %>/', src: ['LICENSE-MIT', 'README.md', 'CHANGELOG.txt']}
]
}
}
});
//test task
grunt.registerTask('test', ['jshint', 'connect', 'qunit:bootstrap5']);
// Default task.
grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'copy']);
// alive server
grunt.registerTask('server', 'connect:server:keepalive');
// build
grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'copy']);
//to run particular task use ":", e.g. copy:libs
};

View File

@@ -10,6 +10,7 @@ This project was created when we needed a **drop-in replacement** for x-editable
- **Bootstrap 5** compatibility
- **jQuery** support maintained
- **Select dropdowns** - fully functional
- **Select2 support** - advanced select with search/ajax
- **Date pickers** - using bootstrap-datepicker
- **Drop-in replacement** - minimal code changes needed
- **Streamlined codebase** - Bootstrap 5 only, legacy code removed
@@ -28,17 +29,24 @@ php -S 0.0.0.0:8000
The demo showcases:
- Select inputs with AJAX and static data sources
- Select2 inputs with search functionality (requires select2 library)
- Date picker functionality
- Basic in-place editing
## Installation
### Via npm
```bash
npm install x-editable-bootstrap5
```
### Dependencies
This library requires:
This library automatically installs and requires:
- **Bootstrap 5** (CSS and JS)
- **jQuery 3.x**
- **bootstrap-datepicker** (for date inputs)
- **bootstrap-datepicker** (for date inputs - included as dependency)
- **select2** (for select2 inputs - included as dependency)
### Quick Start
@@ -51,15 +59,31 @@ This library requires:
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- Bootstrap Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<!-- Bootstrap Datepicker -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.10.0/css/bootstrap-datepicker.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.10.0/js/bootstrap-datepicker.min.js"></script>
<!-- X-Editable Bootstrap 5 -->
<link href="dist/bootstrap5-editable/css/bootstrap-editable.css" rel="stylesheet">
<link href="dist/bootstrap5-editable/css/select2.min.css" rel="stylesheet">
<script src="dist/bootstrap5-editable/js/bootstrap-editable.js"></script>
```
**Or using npm/webpack:**
```javascript
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
import 'bootstrap-icons/font/bootstrap-icons.css';
import 'bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css';
import 'bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js';
import 'x-editable-bootstrap5/dist/bootstrap5-editable/css/bootstrap-editable.css';
import 'x-editable-bootstrap5/dist/bootstrap5-editable/css/select2.min.css';
import 'x-editable-bootstrap5/dist/bootstrap5-editable/js/bootstrap-editable.js';
```
2. **Initialize editable elements:**
```javascript
$('#my-editable').editable({
@@ -72,14 +96,61 @@ $('#my-editable').editable({
});
```
## Select2 Support
This library includes built-in support for Select2 inputs, providing enhanced select functionality with search, AJAX loading, and more.
**Note:** Select2 is included as an npm dependency and will be automatically installed when you install x-editable-bootstrap5.
### Quick Select2 Setup
**Use select2 type in your editable:**
```javascript
$('#my-select2').editable({
type: 'select2',
source: [
{id: 'us', text: 'United States'},
{id: 'gb', text: 'Great Britain'},
{id: 'de', text: 'Germany'}
],
select2: {
placeholder: 'Select Country',
allowClear: true
},
url: '/update-endpoint'
});
```
### Select2 with AJAX
```javascript
$('#ajax-select2').editable({
type: 'select2',
select2: {
placeholder: 'Search countries...',
minimumInputLength: 2,
ajax: {
url: '/search-countries',
dataType: 'json',
data: function (term) {
return { query: term };
},
results: function (data) {
return { results: data };
}
}
},
url: '/update-endpoint'
});
```
## Migration from Bootstrap 3
If you're migrating from the original x-editable:
1. **Update Bootstrap** to version 5
2. **Add bootstrap-datepicker** dependency (no longer bundled)
3. **Replace x-editable files** with this Bootstrap 5 version
4. **Update CSS classes** if using custom styling (Bootstrap 3 → 5 changes)
2. **Replace x-editable files** with this Bootstrap 5 version (bootstrap-datepicker included as dependency)
3. **Update CSS classes** if using custom styling (Bootstrap 3 → 5 changes)
The JavaScript API remains largely the same, making it a true drop-in replacement.
@@ -98,6 +169,16 @@ grunt build
npx webpack --mode=development
```
## Repository
**Main Repository:** [git.24unix.net/tracer/x-editable-bs5](https://git.24unix.net/tracer/x-editable-bs5)
**Mirrors:**
- GitHub: [github.com/24unix/x-editable-bs5](https://github.com/24unix/x-editable-bs5)
- GitLab: [gitlab.com/24unix/x-editable-bs5](https://gitlab.com/24unix/x-editable-bs5)
Development happens on the main repository at git.24unix.net, with mirrors automatically synced to GitHub and GitLab.
## License
This project maintains the same MIT license as the original x-editable project.

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,19 +1,27 @@
import $ from 'jquery';
// Ensure jQuery is available globally before any other imports
// Ensure jQuery is available globally before importing x-editable
window.$ = window.jQuery = $;
global.$ = global.jQuery = $;
if (typeof global !== 'undefined') {
global.$ = global.jQuery = $;
}
import "bootstrap"
import "bootstrap/dist/css/bootstrap.min.css"
import "bootstrap-icons/font/bootstrap-icons.min.css"
// bootstrap-datepicker loaded separately (not bundled in grunt build)
import "bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js";
// Import bootstrap-datepicker for date inputs
import "bootstrap-datepicker";
import "bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css";
// Import the editable functionality (attaches to jQuery.fn) - using Grunt-built version
require("../dist/bootstrap5-editable/js/bootstrap-editable");
$.fn.editable.defaults.mode = 'inline';
// Import select2 before x-editable
import "select2";
import "select2/dist/css/select2.min.css";
// Import the editable functionality - should be synchronous
import 'dist/bootstrap5-editable/js/bootstrap-editable.js'
import 'dist/bootstrap5-editable/css/bootstrap-editable.css'
// $.fn.editable.defaults.mode = 'inline';
$(function() {
@@ -50,7 +58,7 @@ $(function() {
});
const initialDateValue = new Date().toISOString().split('T')[0];
$('#datepicker').editable({
type: 'date',
url: 'demo/demo.php', // URL to send the POST request
@@ -70,4 +78,32 @@ $(function() {
}
});
// Select2 functionality (now bundled with x-editable)
$('#select2-test').editable({
type: 'select2',
url: 'demo/demo.php',
source: [
{id: 'us', text: 'United States'},
{id: 'gb', text: 'Great Britain'},
{id: 'ru', text: 'Russia'},
{id: 'de', text: 'Germany'},
{id: 'fr', text: 'France'},
{id: 'es', text: 'Spain'},
{id: 'it', text: 'Italy'}
],
value: 'us',
savenochange: true, // Allow saving even when value hasn't changed
select2: {
placeholder: 'Select Country',
allowClear: true
},
success: function(response, newValue) {
// Handle success
},
error: function(response) {
// Handle error
}
});
})

BIN
demo/dist/240c0c6464de0b4bf116.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

BIN
demo/dist/56d4c7ce2d3591a02107.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

1307
demo/dist/app.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@@ -7,7 +7,7 @@
<link rel="stylesheet" href="./dist/bootstrap5-editable/css/bootstrap-editable.css">
<!-- <script src="./dist/bootstrap5-editable/js/bootstrap-editable.js"></script>-->
<!-- <script src="./dist/jquery.js"></script>-->
<script src="./dist/app.js" type="module"></script>
<script src="./demo/dist/app.js" type="module"></script>
<title>Bootstrap 5.3.3 Test</title>
</head>
@@ -47,7 +47,7 @@
</a>
</div>
<div class="container">
<div class="container mb-3">
<h3>Test X-Editable Datepicker</h3>
<p>Click to select a date:</p>
@@ -63,6 +63,22 @@
</a>
</div>
<div class="container mb-3">
<h3>Test X-Editable Select2 (refactored to work with select2 4.1.0-RC)</h3>
<p>Click to select from a larger list with search functionality:</p>
<a
href="#"
id="select2-test"
class="editable editable-click"
data-type="select2"
data-pk="104"
data-title="Select Country"
>
United States
</a>
</div>
</form>
</body>
</html>

237
dist/CHANGELOG.txt vendored
View File

@@ -1,237 +0,0 @@
X-editable changelog
=============================
Version 1.5.1 Nov 4, 2013
----------------------------
[enh #371] submit single field (vitalets)
[bug] select2: placeholder not shown if value initially empty (vitalets)
[enh #400] allow `validate` to change submitted value, also fix #354 (vitalets)
[enh #396] bs3 popover: placement `auto` (vitalets)
[bug #357] select2: tags mode with space separator (vitalets)
[bug #374] dateui: clear button does not submit (vitalets)
Version 1.5.0 Oct 1, 2013
----------------------------
[enh #362] add twitter typeahead.js (vitalets)
[enh] select: add `sourceOptions` to modify source request method and params (vitalets)
[enh #377] add bool option `escape` to allow html as content (vitalets)
[bug #344] fix determing empty for html content (vitalets)
[enh] update select2 to 3.4.3 (vitalets)
[enh #343] Bootstrap 3 support (vitalets)
Version 1.4.6 Aug 8, 2013
----------------------------
[bug #312] can't apply selector more than once (vitalets)
[enh #48] textarea: use `white-space: pre-wrap` instead of nl2br conversion (vitalets)
[enh #286] added HTML5 time input (Doggie52)
[enh] add `defaultValue` option (vitalets)
[enh #313] add composer support (masim)
[enh #300] Fix 'bootstrap popover falls off page if editable is too close to window edge' (belerweb)
[enh #302] allow data-datepicker and data-datetimepicker (vitalets)
[enh #287] add option to disable item in select (vitalets)
[enh #281] add collision flag to adjust tooltip position (vitalets)
[bug #279] fix jQuery UI tooltip z-index to be less than select2 dropdown (vitalets)
[bug #276] support id() and text() functions of select2 (vitalets)
Version 1.4.5 Jun 23, 2013
----------------------------
[enh #245] highlight element after update (vitalets)
[enh] select2 now works with ajax source (vitalets)
[bug] fix datefield (datetimefield) to return null for incorrect dates (vitalets)
[bug #224] do not close popup when it is saving value (vitalets)
[enh] added `submitValue` to `save` event params (vitalets)
[enh #259] allow `getValue` method to return value itself, not object (vitalets)
[enh] add `destroy` method to inputs (vitalets)
[enh #164] allow emptytext to be html (vitalets)
[enh #78] allow html in editable content (vitalets)
[enh] update container position when datetimepicker viewMode changes (vitalets)
[enh #255] remove xxxView options from first level config of datetimepicker (vitalets)
[enh] if `display` defined as function call it on init (vitalets)
[enh #218] sourceCache now disables cache totally (vitalets)
[bug #156] solve conflict of bootstrap datepicker and jQuery UI datepicker (vitalets)
[enh] update bootstrap-datepicker to 1.1.2 (vitalets)
[enh] allow follow links in disabled state (vitalets)
[enh] update combodate to 1.0.4, fix #222 (vitalets)
Version 1.4.4 May 4, 2013
----------------------------
[enh #219] added `error` callback (joekaiser)
[enh #198] new value of showbuttons: 'bottom' (vitalets)
[enh #192] add class editable-popup to have diferent css for popup and inline (vitalets)
[enh] update to bootstrap-datepicker 1.0.2 (vitalets)
[enh] update to combodate 1.0.3 with yearDescending and roundTime options (vitalets)
[enh] add 'use strict' directive (vitalets)
[enh #202] allow pk=0 (mdeweerd)
[enh #183] move datepicker icon to center of button (vitalets)
[enh] upgrade to select2 3.3.2 (vitalets)
[enh #176] update to bootstrap 2.3.1 (vitalets)
[bug #171] clear in date & datetime when showbuttons=false (vitalets)
[bug #166] clear button for input type=number (vitalets)
[bug #65] checklist don't show checked for single value (vitalets)
[enh #188] added bootstrap datetime (adeg, vitalets)
[bug] editable-poshytip on inline mode tries to write in $.Poshytip (vitalets)
Version 1.4.3 Mar 8, 2013
----------------------------
[bug #32] hotfix for jQuery UI 1.9+ (vitalets)
Version 1.4.2 Mar 7, 2013
----------------------------
[enh #132] combodate options can be defined via data-combodate json string (vitalets)
[enh] source defined as function now has scope of element and can return string used as url (vitalets)
[bug #99] select2 with Hierarchical Data (kev360)
[bug #81] wysihtml5: fix inserting image (vitalets)
[bug] remove $.browser from wysihtml5 input to support jQuery 1.9 (vitalets)
[bug #142] editable poshytip jquery 1.9+ compatibility (spiderpug)
[enh #126] Update bootstrap datepicker library and add minViewMode to options (kev360)
[enh #150] select2 with showbuttons = false (vitalets)
[bug #149] datepicker not shown when showbuttons = false (vitalets)
[bug #133] clear button incorect position due to parent line-height property (vitalets)
[bug #141] data-value ignored for empty elements (vitalets)
[bug #137] fix empty class for delegated element (vitalets)
[enh #121] add support of momentjs 2.0.0 in combodate (vitalets)
Version 1.4.1 Jan 18, 2013
----------------------------
[enh #62] new option `selector` to work with delegated targets (vitalets)
[enh] new option `unsavedclass` to set css class when value was not sent to server (vitalets)
[enh] new option `emptyclass` to set css class when element is empty (vitalets)
[enh #59] select2 input (vitalets)
[enh #17] typeahead input (vitalets)
[enh] select: support of OPTGROUP via `children` key in source (vitalets)
[enh] checklist: set checked via prop instead of attr (vitalets)
Version 1.4.0 Jan 11, 2013
----------------------------
[enh] added new input type: combodate (vitalets)
[bug #68] allow arrays for data attributes (adimitrov)
[enh] setValue method updates input if form is open (vitalets)
[enh] select: change source via option method, see #61 (vitalets)
[bug] select: source loaded twice if sourceCache = false (vitalets)
[enh] added `destroy` method, see #61 (vitalets)
[enh] textarea: added `rows` property (vitalets)
[enh #60] added wysihtml5 input (vitalets)
[enh] added IOS-style clear button for text inputs (vitalets)
[enh] date inputs changed in inline mode (vitalets)
[enh #51] popup/inline modes can be toggled via `mode` config option. No more *-inline.js versions of files (vitalets)
[enh] update bootstrap-datepicker to upstream (vitalets)
[enh] 'display' method: added param 'response' allowing to show text directly from server (vitalets)
[enh] new util method `$.fn.editableutils.itemsByValue` to easily get selected items for sourced-inputs (vitalets)
[enh] convert newlines to <br> in error message for more pretty display (vitalets)
[enh #57] remove css height for textarea (vitalets)
[enh] if new value for select is 'null' source should not load (vitalets)
[enh #53] 'name' no more appended to source defined as url (vitalets)
[enh #46] move 'img' dir outside 'css' (vitalets)
[enh #48] fix handling of newlines in textarea input (jmfontaine)
[enh #47] set select source to function (brianchance)
[bug] fix inline container move on next line in IE7 (vitalets)
Version 1.3.0 Dec 10, 2012
----------------------------
[enh] added html5 inputs support: password, email, url, tel, number, range (vitalets)
[bug #43] fix for bootstrap 2.2.2 (vitalets)
[enh #41] 'abstract' class renamed to 'abstractinput' as abstract is reserved word (vitalets)
[enh #40] 'params' option defined as function overwrites original ajax data instead of appending (vitalets)
[bug] datepicker: error when click on arrows after clear date (vitalets)
[enh] 'hidden' event: added possible value of reason param - 'nochange'. Occurs when form is submitted but value was not changed (vitalets)
[enh] 'submit' method changed: error-callback's parameter simplified (vitalets)
[enh] 'submit' method changed: now when response 200 OK it does not set pk automatically (vitalets)
[enh] 'submit' method changed: removed dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets)
[enh] removed default ajax dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets)
[enh] select: do not show 'sourceError' in element during autotext execution (vitalets)
Version 1.2.0 Dec 6, 2012
----------------------------
[enh #36] 'submit' method: added 'ajaxOptions' property to modify ajax request (vitalets)
[enh] inputs now internally use 'value2submit' method instead of previous 'value2str' (vitalets)
[enh] editableContainer removed from docs (vitalets)
[enh] editableContainer: removed 'autohide' option and 'cancel' event. Use 'hidden' event instead (vitalets)
[enh] 'hidden' event: added param 'reason' that points to reason caused hiding (vitalets)
[enh] 'select' submit by enter (vitalets)
[bug #37] fix incorrectly shown datepicker in jquery 1.7.1 + webkit (vitalets)
[enh] added url param 'jquery' to run tests in different versions of jquery, e.g. '&jquery=1.7.2' (vitalets)
[enh] 'enablefocus' option removed. More efficient to use 'save/hide' events to set focus to any element (vitalets)
[enh] 'init' event was added due to removal of render event (vitalets)
[enh] 'render' event was removed, use 'display' callback instead (vitalets)
[enh] 'checklist' submit value as array, not comma separated string (vitalets)
[enh] 'checklist' was refactored: options 'viewseparator', 'limit', 'limitText' are supressed by 'display' callback (vitalets)
[enh] new option: 'display' callback. Makes far more flexible rendering value into element's text. (vitalets)
[bug] fix typos (atrophic)
[enh] all callbacks scope changed to element (vitalets)
[enh] new option: 'savenochange' to save or cancel value when it was not changed in form (vitalets)
[enh] composite pk can be defined as JSON in data-pk attribute (vitalets)
[enh #30] new option 'sourceCache' true|false to disable cache for select (vitalets)
[bug #34] inputclass span* broken with fluid bootstrap layout. Classes changed to 'input-*'. (vitalets)
[enh] utils now added to $.fn.editableutils instead of $.fn.editableform.utils (vitalets)
[enh] input types now added to $.fn.editabletypes instead of $.fn.editableform.types (vitalets)
[enh] playground and tests now use requirejs (vitalets)
[bug #27] 'today' button toggle bug in bootstrap-datepicker (vitalets)
Version 1.1.1 Nov 30, 2012
----------------------------
[enh] 'showbuttons' option to hide buttons in form (vitalets)
[enh] object can be passed in 'option' method to set several options at once (vitalets)
[enh #20] toggle editable by 'dblclick' and 'mouseenter' (vitalets)
[enh] added 'inputs-ext' directory with sample input 'address'. They will not be concatenated to main files (vitalets)
[enh #13] 'onblur' option: to cancel, submit or ignore when user clicks outside the form (vitalets)
[enh] 'ajaxOptions' parameter for advanced ajax configuration (vitalets)
[enh] 'success' callback can return object to overwrite submitted value (vitalets)
Version 1.1.0 Nov 27, 2012
----------------------------
[enh #11] icon cancel changed to 'cross' (tarciozemel)
[enh] added support for IE7+ (vitalets)
[enh #9] 'name' or 'id' is not required anymore (vitalets)
[enh] 'clear' button added in date and dateui (vitalets)
[enh] form template changed: added DIV.editable-input, DIV.editable.buttons and $.fn.editableform.buttons (vitalets)
[enh] new input type: checklist (vitalets)
[enh] updated docs: inputs dropdown menu, global templates section (vitalets)
Version 1.0.1 Nov 22, 2012
----------------------------
[enh] contribution guide in README.md (vitalets)
[enh #7] 'shown', 'hidden' events added (vitalets)
[enh #1] params can be a function to calculate it dynamically (vitalets)
[enh #6] do not preventDefault() in click when toggle='manual'. This allows to have clickable links (vitalets)
[bug #3] should not mark element with unsave css if url is user's function (vitalets)
Version 1.0.0 Nov 19, 2012
----------------------------
Initial release. This library is new life of bootstrap-editable (1.1.4) that was strongly refactored and improved.
Main features:
- support not only bootstrap but any core library: bootstrap, jquery-ui or pure jquery
- different container classes to show form: popover, tooltip, poshytip, etc
- inline and popup versions
- new directory structure and logic in separate js files allowing easy contribution
It is not fully compatible with bootstrap-editable but has mainly the same interface and api.
Here list of differences to help you to upgrade your application:
[change] 'toggle' option value can be only click|manual (not toggling element id). In case of 'manual' you should write handler calling 'show' method.
[change] 'validate' option cannot be defined as object anymore.
[change] events 'init', 'update', 'shown', 'hidden' removed. Events 'save', 'cancel' added. Event 'render' remains.
[change] input's option 'template' renamed to 'tpl' (to exclude conflict with container's template).
[change] value can be stored internally as object (previously was always string). Useful for date input.
[change] 'error' callback option is removed. 'success' callback remained.
[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compatibility.
[enh] api method 'setValue' to set manually value of editable.
[change] locales directory is excluded from bootstrap-datepicker input. If you need localization you should jus download corresponding file from github.
[change] date and dateui specific options can be set only via 'datepicker' option in first level of config (previously it was possible to set some options directly in config, e.g. weekStart).
[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occurred anyway)
Also all known bugs of bootstrap-editable were closed.

22
dist/LICENSE-MIT vendored
View File

@@ -1,22 +0,0 @@
Copyright (c) 2012 Vitaliy Potapov
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

17
dist/README.md vendored
View File

@@ -1,17 +0,0 @@
# X-Editable (Bootstrap 5 Fork)
This project is a fork of [vitalets/x-editable](https://github.com/vitalets/x-editable), adapted to work with **Bootstrap 5** while maintaining compatibility with jQuery.
## Why This Fork?
The original **x-editable** library was designed for Bootstrap 3 and has not been actively maintained. This fork modernizes the codebase and updates it to support:
- **Bootstrap 5**
- **Bootstrap Icons** (replacing Glyphicons)
NOTE: This repo has not yet been completely tested and is not available via NPM right now!
Later:
### Using npm:
```sh
npm install x-editable-bootstrap5
```

2
dist/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,322 +0,0 @@
/*!
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Datepicker for Bootstrap v1.10.0 (https://github.com/uxsolutions/bootstrap-datepicker)
*
* Licensed under the Apache License v2.0 (https://www.apache.org/licenses/LICENSE-2.0)
*/
/*!
* jQuery JavaScript Library v3.7.1
* https://jquery.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2023-08-28T13:37Z
*/
/*!****************************!*\
!*** ./src/inputs/list.js ***!
\****************************/
/*!****************************!*\
!*** ./src/inputs/text.js ***!
\****************************/
/*!******************************!*\
!*** ./src/inputs/select.js ***!
\******************************/
/*!********************************!*\
!*** ./src/inputs/abstract.js ***!
\********************************/
/*!********************************!*\
!*** ./src/inputs/textarea.js ***!
\********************************/
/*!*********************************!*\
!*** ./src/inputs/date/date.js ***!
\*********************************/
/*!************************************!*\
!*** ./src/bootstrap5-editable.js ***!
\************************************/
/*!**************************************!*\
!*** ./src/inputs/date/datefield.js ***!
\**************************************/
/*!*****************************************!*\
!*** ./src/element/editable-element.js ***!
\*****************************************/
/*!*******************************************!*\
!*** ./src/containers/editable-inline.js ***!
\*******************************************/
/*!********************************************!*\
!*** ./node_modules/jquery/dist/jquery.js ***!
\********************************************/
/*!********************************************!*\
!*** ./src/editable-form/editable-form.js ***!
\********************************************/
/*!*********************************************!*\
!*** ./src/containers/editable-popover5.js ***!
\*********************************************/
/*!**********************************************!*\
!*** ./src/containers/editable-container.js ***!
\**********************************************/
/*!**************************************************!*\
!*** ./node_modules/@popperjs/core/lib/enums.js ***!
\**************************************************/
/*!**************************************************!*\
!*** ./node_modules/@popperjs/core/lib/index.js ***!
\**************************************************/
/*!**************************************************!*\
!*** ./src/editable-form/editable-form-utils.js ***!
\**************************************************/
/*!***************************************************!*\
!*** ./node_modules/@popperjs/core/lib/popper.js ***!
\***************************************************/
/*!*******************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/math.js ***!
\*******************************************************/
/*!*******************************************************!*\
!*** ./src/editable-form/editable-form-bootstrap5.js ***!
\*******************************************************/
/*!********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/popper-lite.js ***!
\********************************************************/
/*!*********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/createPopper.js ***!
\*********************************************************/
/*!*********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/within.js ***!
\*********************************************************/
/*!*********************************************************!*\
!*** ./node_modules/bootstrap/dist/js/bootstrap.esm.js ***!
\*********************************************************/
/*!***********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/flip.js ***!
\***********************************************************/
/*!***********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/hide.js ***!
\***********************************************************/
/*!***********************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/debounce.js ***!
\***********************************************************/
/*!************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/arrow.js ***!
\************************************************************/
/*!************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/index.js ***!
\************************************************************/
/*!************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/userAgent.js ***!
\************************************************************/
/*!*************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/offset.js ***!
\*************************************************************/
/*!*************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getAltAxis.js ***!
\*************************************************************/
/*!**************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/mergeByName.js ***!
\**************************************************************/
/*!***************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/contains.js ***!
\***************************************************************/
/*!***************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getVariation.js ***!
\***************************************************************/
/*!****************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getWindow.js ***!
\****************************************************************/
/*!*****************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/instanceOf.js ***!
\*****************************************************************/
/*!*****************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/computeOffsets.js ***!
\*****************************************************************/
/*!*****************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/detectOverflow.js ***!
\*****************************************************************/
/*!*****************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/orderModifiers.js ***!
\*****************************************************************/
/*!******************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getNodeName.js ***!
\******************************************************************/
/*!******************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/applyStyles.js ***!
\******************************************************************/
/*!******************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/expandToHashMap.js ***!
\******************************************************************/
/*!*******************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getBasePlacement.js ***!
\*******************************************************************/
/*!*******************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/rectToClientRect.js ***!
\*******************************************************************/
/*!********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js ***!
\********************************************************************/
/*!********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js ***!
\********************************************************************/
/*!********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getParentNode.js ***!
\********************************************************************/
/*!********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/computeStyles.js ***!
\********************************************************************/
/*!********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/popperOffsets.js ***!
\********************************************************************/
/*!*********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js ***!
\*********************************************************************/
/*!*********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/isTableElement.js ***!
\*********************************************************************/
/*!*********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/eventListeners.js ***!
\*********************************************************************/
/*!*********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getFreshSideObject.js ***!
\*********************************************************************/
/*!*********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/mergePaddingObject.js ***!
\*********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js ***!
\**********************************************************************/
/*!**********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/modifiers/preventOverflow.js ***!
\**********************************************************************/
/*!***********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js ***!
\***********************************************************************/
/*!***********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js ***!
\***********************************************************************/
/*!***********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js ***!
\***********************************************************************/
/*!***********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js ***!
\***********************************************************************/
/*!***********************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getOppositePlacement.js ***!
\***********************************************************************/
/*!************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js ***!
\************************************************************************/
/*!*************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js ***!
\*************************************************************************/
/*!**************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js ***!
\**************************************************************************/
/*!***************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js ***!
\***************************************************************************/
/*!***************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js ***!
\***************************************************************************/
/*!***************************************************************************!*\
!*** ./node_modules/bootstrap-datepicker/dist/js/bootstrap-datepicker.js ***!
\***************************************************************************/
/*!****************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js ***!
\****************************************************************************/
/*!********************************************************************************!*\
!*** ./node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js ***!
\********************************************************************************/

1
dist/app.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,3 @@
/*! X-editable - v1.5.2
* A maintained fork of x-editable for Bootstrap 5 support.
* https://git.24unix.net/tracer/x-editable
* Copyright (c) 2025 Micha Espey; Licensed MIT */
.editableform {
margin-bottom: 0; /* overwrites bootstrap margin */
}
@@ -170,69 +166,72 @@
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
.editable-container.editable-popup {
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
}
.editable-container.popover {
width: auto; /* without this rule popover does not stretch */
/* Bootstrap 5 inline editing fixes */
.editable-inline .editableform {
display: inline-flex !important;
flex-direction: row !important;
align-items: center !important;
gap: 0.5rem !important;
flex-wrap: nowrap !important;
}
.editable-container.editable-inline {
display: inline-block;
vertical-align: middle;
width: auto;
/* inline-block emulation for IE7*/
zoom: 1;
*display: inline;
.editable-inline .editable-input {
flex-shrink: 1 !important;
min-width: 0 !important;
max-width: 200px !important; /* Prevent overly wide selects */
display: inline-block !important;
vertical-align: middle !important;
}
.editable-container.ui-widget {
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
}
.editable-click,
a.editable-click,
a.editable-click:hover {
text-decoration: none;
border-bottom: dashed 1px #0088cc;
.editable-inline .editable-input select {
max-width: 100% !important;
min-width: 120px !important;
}
.editable-click.editable-disabled,
a.editable-click.editable-disabled,
a.editable-click.editable-disabled:hover {
color: #585858;
cursor: default;
border-bottom: none;
.editable-inline .editable-buttons {
flex-shrink: 0 !important;
margin-left: 0.5rem !important;
margin-top: 0 !important;
display: inline-flex !important;
align-items: center !important;
gap: 0.25rem !important;
vertical-align: middle !important;
}
.editable-empty, .editable-empty:hover, .editable-empty:focus{
font-style: italic;
color: #DD1144;
/* border-bottom: none; */
text-decoration: none;
.editable-inline .control-group {
white-space: nowrap !important;
display: inline-flex !important;
align-items: center !important;
}
.editable-unsaved {
font-weight: bold;
/* Improve button styling for Bootstrap 5 */
.editable-buttons .btn {
padding: 0.25rem 0.5rem;
line-height: 1.2;
border-radius: 0.25rem;
}
.editable-unsaved:after {
/* content: '*'*/
.editable-buttons .btn-sm {
padding: 0.125rem 0.25rem;
font-size: 0.875rem;
}
.editable-bg-transition {
-webkit-transition: background-color 1400ms ease-out;
-moz-transition: background-color 1400ms ease-out;
-o-transition: background-color 1400ms ease-out;
-ms-transition: background-color 1400ms ease-out;
transition: background-color 1400ms ease-out;
/* Hide buttons initially for datepicker inputs - using discovered DOM structure */
/* Buttons are siblings to editable-input that contains datepicker */
.editable-input:has(.input-group.date) + .editable-buttons,
.editable-input:has(.input-group.datepicker-above) + .editable-buttons,
/* Buttons might be in same container as editable-input */
*:has(.editable-input .input-group.date) .editable-buttons,
*:has(.editable-input .input-group.datepicker-above) .editable-buttons {
display: none !important;
visibility: hidden !important;
}
/*see https://github.com/vitalets/x-editable/issues/139 */
.form-horizontal .editable
{
padding-top: 5px;
display:inline-block;
/* Show buttons when they have the show-buttons class */
.editable-input:has(.input-group.date) + .editable-buttons.show-buttons,
.editable-input:has(.input-group.datepicker-above) + .editable-buttons.show-buttons,
*:has(.editable-input .input-group.date) .editable-buttons.show-buttons,
*:has(.editable-input .input-group.datepicker-above) .editable-buttons.show-buttons {
display: inline-flex !important;
visibility: visible !important;
}

View File

@@ -1,167 +0,0 @@
.editableform {
margin-bottom: 0; /* overwrites bootstrap margin */
}
.editableform .control-group {
margin-bottom: 0; /* overwrites bootstrap margin */
white-space: nowrap; /* prevent wrapping buttons on new line */
line-height: 20px; /* overwriting bootstrap line-height. See #133 */
}
/*
BS3 fix: stop css from breaking when the form is inside a popup and inside a form with the class .form-horizontal
See: https://github.com/vitalets/x-editable/issues/682
*/
.form-horizontal .editable-popup .editableform .form-group {
margin-left:0;
margin-right:0;
}
/*
BS3 width:1005 for inputs breaks editable form in popup
See: https://github.com/vitalets/x-editable/issues/393
*/
.editableform .form-control {
width: auto;
}
.editable-buttons {
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
vertical-align: top;
margin-left: 7px;
/* inline-block emulation for IE7*/
zoom: 1;
*display: inline;
}
.editable-buttons.editable-buttons-bottom {
display: block;
margin-top: 7px;
margin-left: 0;
}
.editable-input {
vertical-align: top;
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
white-space: normal; /* reset white-space decalred in parent*/
/* display-inline emulation for IE7*/
zoom: 1;
*display: inline;
}
.editable-buttons .editable-cancel {
margin-left: 7px;
}
/*for jquery-ui buttons need set height to look more pretty*/
.editable-buttons button.ui-button-icon-only {
height: 24px;
width: 30px;
}
.editableform-loading {
background: url('../img/loading.gif') center center no-repeat;
height: 25px;
width: auto;
min-width: 25px;
}
.editable-inline .editableform-loading {
background-position: left 5px;
}
.editable-error-block {
max-width: 300px;
margin: 5px 0 0 0;
width: auto;
white-space: normal;
}
/*add padding for jquery ui*/
.editable-error-block.ui-state-error {
padding: 3px;
}
.editable-error {
color: red;
}
/* ---- For specific types ---- */
.editableform .editable-date {
padding: 0;
margin: 0;
float: left;
}
/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
.editable-inline .add-on .icon-th {
margin-top: 3px;
margin-left: 1px;
}
/* checklist vertical alignment */
.editable-checklist label input[type="checkbox"],
.editable-checklist label span {
vertical-align: middle;
margin: 0;
}
.editable-checklist label {
white-space: nowrap;
}
/* set exact width of textarea to fit buttons toolbar */
.editable-wysihtml5 {
width: 566px;
height: 250px;
}
/* clear button shown as link in date inputs */
.editable-clear {
clear: both;
font-size: 0.9em;
text-decoration: none;
text-align: right;
}
/* IOS-style clear button for text inputs */
.editable-clear-x {
background: url('../img/clear.png') center center no-repeat;
display: block;
width: 13px;
height: 13px;
position: absolute;
opacity: 0.6;
z-index: 100;
top: 50%;
right: 6px;
margin-top: -6px;
}
.editable-clear-x:hover {
opacity: 1;
}
.editable-pre-wrapped {
white-space: pre-wrap;
}
/* Position datepicker above input for datepicker-above class */
.datepicker-above .datepicker-inline {
position: absolute;
bottom: 100%;
left: 0;
right: 0;
z-index: 1000;
margin-bottom: 5px;
background: white;
border: 1px solid #dee2e6;
border-radius: 0.375rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

File diff suppressed because one or more lines are too long

View File

@@ -1,22 +0,0 @@
/*!
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Datepicker for Bootstrap v1.10.0 (https://github.com/uxsolutions/bootstrap-datepicker)
*
* Licensed under the Apache License v2.0 (https://www.apache.org/licenses/LICENSE-2.0)
*/
/*!
* jQuery JavaScript Library v3.7.1
* https://jquery.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2023-08-28T13:37Z
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/jquery.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +0,0 @@
/*!
* jQuery JavaScript Library v3.7.1
* https://jquery.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2023-08-28T13:37Z
*/

1
dist/jquery.js.map vendored

File diff suppressed because one or more lines are too long

893
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{
"name": "@24unix/x-editable",
"title": "X-editable",
"name": "x-editable-bootstrap5",
"title": "X-editable Bootstrap 5",
"description": "A maintained fork of x-editable for Bootstrap 5 support.",
"version": "1.5.2",
"version": "25.0.7",
"homepage": "https://git.24unix.net/tracer/x-editable",
"author": {
"name": "Micha Espey",
@@ -18,8 +18,12 @@
],
"repository": {
"type": "git",
"url": "https://git.24unix.net/tracer/x-editable.git"
"url": "https://git.24unix.net/tracer/x-editable-bs5.git"
},
"mirrors": [
"https://github.com/24unix/x-editable-bs5",
"https://gitlab.com/24unix/x-editable-bs5"
],
"bugs": {
"url": "https://git.24unix.net/tracer/x-editable/issues"
},
@@ -35,17 +39,28 @@
"bootstrap": "^5.3.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-icons": "^1.11.3",
"jquery": "^3.7.1"
"jquery": "^3.7.1",
"select2": "^4.1.0-rc.0"
},
"scripts": {
"build:lib": "webpack --mode development --config webpack.lib.js",
"build:demo": "webpack --mode development --config webpack.demo.js",
"dev": "npm run build:lib && npm run build:demo",
"watch": "webpack --mode development --watch",
"prod": "webpack --mode production"
},
"devDependencies": {
"grunt": "^1.6.1",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"grunt-contrib-clean": "^2.0.1",
"grunt-contrib-concat": "^2.1.0",
"grunt-contrib-connect": "^5.0.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-jshint": "^3.2.0",
"grunt-contrib-qunit": "^10.1.1",
"grunt-contrib-uglify": "^5.2.2"
"grunt-contrib-uglify": "^5.2.2",
"style-loader": "^4.0.0",
"webpack-cli": "^6.0.1"
},
"keywords": [
"editable",

View File

@@ -1,32 +1,62 @@
/*
X-Editable Bootstrap 5 - Complete Bundle
Uses npm bootstrap-datepicker instead of bundled version
Order matches Gruntfile.js for compatibility
Clean ES6 Module approach - all modules converted
*/
import $ from "jquery";
// Import bootstrap-datepicker from npm
import "bootstrap-datepicker";
import 'select2';
import 'select2/dist/css/select2.min.css';
// Core editable functionality - EXACT ORDER from Gruntfile
import "./editable-form/editable-form.js";
// Import all modules (functions will be available globally after import)
import "./editable-form/editable-form-utils.js";
import "./containers/editable-container.js";
import "./containers/editable-inline.js";
import "./element/editable-element.js";
import "./inputs/abstract.js";
import "./element/editable-element.js";
import "./inputs/list.js";
import "./inputs/text.js";
import "./inputs/textarea.js";
import "./inputs/select.js";
// Date input (now uses npm bootstrap-datepicker)
import "./inputs/select2/select2.js";
import "./inputs/date/date.js";
import "./inputs/date/datefield.js";
// Bootstrap 5 specific containers and forms
import "./editable-form/editable-form.js";
import "./containers/editable-container.js";
import "./containers/editable-inline.js";
import "./containers/editable-popover5.js";
import "./editable-form/editable-form-bootstrap5.js";
// Export jQuery for compatibility
export default $;
// Export initialization function - UMD will call this with jQuery
export default function initializeXEditable($) {
// UMD factory will pass jQuery as first parameter
if (!$ || !$.fn) {
console.error('x-editable: jQuery not found or invalid jQuery instance provided');
return;
}
console.log('x-editable build: Using jQuery version =', $.fn.jquery);
// Initialize x-editable synchronously in correct order
// Step 1: Attach foundational utilities
attachEditableUtils($);
attachAbstractInput($);
// Step 2: Attach all input types and containers
attachList($);
attachText($);
attachTextarea($);
attachSelect($);
attachSelect2($);
attachDate($);
attachDateField($);
attachEditableForm($);
attachEditableContainer($);
attachEditableInline($);
attachEditablePopover($);
attachEditableFormBootstrap($);
// Step 3: Finally attach the main editable functionality
attachEditable($);
console.log('x-editable build: Editable attached =', typeof $.fn.editable);
console.log('x-editable build: Select2 attached =', typeof $.fn.select2);
return $; // Return jQuery instance for chaining
}

View File

@@ -7,7 +7,7 @@
@class editableContainer
@uses editableform
**/
(function ($) {
function attachEditableContainer($) {
"use strict";
var Popup = function (element, options) {
@@ -518,4 +518,5 @@
}
};
}(window.jQuery));
return $;
}

View File

@@ -2,7 +2,7 @@
* Editable Inline
* ---------------------
*/
(function ($) {
function attachEditableInline($) {
"use strict";
//copy prototype from EditableContainer
@@ -51,4 +51,5 @@
}
});
}(window.jQuery));
return $;
}

View File

@@ -5,7 +5,7 @@
*/
import { Popover } from "bootstrap";
(function ($) {
function attachEditablePopover($) {
"use strict";
//extend methods
@@ -75,5 +75,6 @@ import { Popover } from "bootstrap";
return this.container() ? $(this.container().tip) : null;
}
});
}(window.jQuery));
return $;
}

View File

@@ -1,9 +1,7 @@
/*
Editableform based on Twitter Bootstrap 5
*/
import $ from "jquery";
(function ($) {
function attachEditableFormBootstrap5($) {
"use strict";
//store parent methods
@@ -57,4 +55,6 @@ import $ from "jquery";
$.fn.editableform.errorBlockClass = null;
//engine
$.fn.editableform.engine = 'bs5';
}(window.jQuery));
return $;
}

View File

@@ -1,7 +1,8 @@
/**
* EditableForm utilites
*/
(function ($) {
function attachEditableUtils($) {
"use strict";
//utils
@@ -246,4 +247,7 @@
}
};
}(window.jQuery));
// Return the jQuery object with attached utilities
return $;
}

View File

@@ -165,3 +165,73 @@
border-radius: 0.375rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
/* Bootstrap 5 inline editing fixes */
.editable-inline .editableform {
display: inline-flex !important;
flex-direction: row !important;
align-items: center !important;
gap: 0.5rem !important;
flex-wrap: nowrap !important;
}
.editable-inline .editable-input {
flex-shrink: 1 !important;
min-width: 0 !important;
max-width: 200px !important; /* Prevent overly wide selects */
display: inline-block !important;
vertical-align: middle !important;
}
.editable-inline .editable-input select {
max-width: 100% !important;
min-width: 120px !important;
}
.editable-inline .editable-buttons {
flex-shrink: 0 !important;
margin-left: 0.5rem !important;
margin-top: 0 !important;
display: inline-flex !important;
align-items: center !important;
gap: 0.25rem !important;
vertical-align: middle !important;
}
.editable-inline .control-group {
white-space: nowrap !important;
display: inline-flex !important;
align-items: center !important;
}
/* Improve button styling for Bootstrap 5 */
.editable-buttons .btn {
padding: 0.25rem 0.5rem;
line-height: 1.2;
border-radius: 0.25rem;
}
.editable-buttons .btn-sm {
padding: 0.125rem 0.25rem;
font-size: 0.875rem;
}
/* Hide buttons initially for datepicker inputs - using discovered DOM structure */
/* Buttons are siblings to editable-input that contains datepicker */
.editable-input:has(.input-group.date) + .editable-buttons,
.editable-input:has(.input-group.datepicker-above) + .editable-buttons,
/* Buttons might be in same container as editable-input */
*:has(.editable-input .input-group.date) .editable-buttons,
*:has(.editable-input .input-group.datepicker-above) .editable-buttons {
display: none !important;
visibility: hidden !important;
}
/* Show buttons when they have the show-buttons class */
.editable-input:has(.input-group.date) + .editable-buttons.show-buttons,
.editable-input:has(.input-group.datepicker-above) + .editable-buttons.show-buttons,
*:has(.editable-input .input-group.date) .editable-buttons.show-buttons,
*:has(.editable-input .input-group.datepicker-above) .editable-buttons.show-buttons {
display: inline-flex !important;
visibility: visible !important;
}

View File

@@ -7,7 +7,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
@uses text
@uses textarea
**/
(function ($) {
function attachEditableForm($) {
"use strict";
var EditableForm = function (div, options) {
@@ -197,7 +197,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
e.preventDefault();
//get new value from input
var newValue = this.input.input2value();
var newValue = this.input.input2value();
//validation: if validate returns string or truthy value - means error
//if returns object like {newValue: '...'} => submitted value is reassigned to it
@@ -632,4 +632,6 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
//engine
$.fn.editableform.engine = 'jquery';
}(window.jQuery));
return $;
}

View File

@@ -4,7 +4,8 @@ Makes editable any HTML element on the page. Applied as jQuery method.
@class editable
@uses editableContainer
**/
(function ($) {
function attachEditable($) {
"use strict";
var Editable = function (element, options) {
@@ -72,6 +73,11 @@ Makes editable any HTML element on the page. Applied as jQuery method.
//attach handler activating editable. In disabled mode it just prevent default action (useful for links)
if(this.options.toggle !== 'manual') {
this.$element.addClass('editable-click');
// Debug: ensure toggle is set
if (!this.options.toggle) {
console.warn('Toggle option is undefined, defaulting to click');
this.options.toggle = 'click';
}
this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){
//prevent following link if editable enabled
if(!this.options.disabled) {
@@ -858,4 +864,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
highlight: '#FFFF80'
};
}(window.jQuery));
// Return the jQuery object with attached editable functionality
return $;
}

View File

@@ -5,7 +5,8 @@ To create your own input you can inherit from this class.
@class abstractinput
**/
(function ($) {
function attachAbstractInput($) {
"use strict";
//types
@@ -216,5 +217,7 @@ To create your own input you can inherit from this class.
};
$.extend($.fn.editabletypes, {abstractinput: AbstractInput});
}(window.jQuery));
// Return the jQuery object with attached abstract input
return $;
}

View File

@@ -23,21 +23,18 @@ $(function(){
});
</script>
**/
(function ($) {
function attachDate($) {
"use strict";
//store bootstrap-datepicker as bdateicker to exclude conflict with jQuery UI one
$.fn.bdatepicker = $.fn.datepicker.noConflict();
if(!$.fn.datepicker) { //if there were no other datepickers, keep also original name
$.fn.datepicker = $.fn.bdatepicker;
}
var Date = function (options) {
console.log('Date input constructor called');
this.init('date', options, Date.defaults);
this.initPicker(options, Date.defaults);
// Ensure type is set correctly
this.type = 'date';
console.log('Date input initialized');
};
$.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput);
@@ -68,7 +65,14 @@ $(function(){
//language
this.options.datepicker.language = this.options.datepicker.language || 'en';
//store DPglobal - use datepicker instead of bdatepicker
//store DPglobal - ensure bootstrap-datepicker is available
if (!$.fn.datepicker || !$.fn.datepicker.DPGlobal) {
console.error('Bootstrap-datepicker not found or DPGlobal not available');
console.error('Please include bootstrap-datepicker.js and bootstrap-datepicker.css in your page');
// Set error state instead of throwing
this.error = 'Bootstrap-datepicker is required but not found. Please include bootstrap-datepicker.js and bootstrap-datepicker.css';
return;
}
this.dpg = $.fn.datepicker.DPGlobal;
//store parsed formats
@@ -77,23 +81,48 @@ $(function(){
},
render: function () {
console.log('Date render method called');
// Ensure we have an input element
if (!this.$input || !this.$input.length) {
console.log('Date render: No input element found');
return;
}
console.log('Date render: Input element found');
// Initialize datepicker immediately
try {
this.$input.datepicker(this.options.datepicker);
console.log('Date render: Datepicker initialized');
// Force set the initial value if we have one
if (this.value) {
this.$input.datepicker('setDate', this.value);
}
} catch (error) {
// Silently handle datepicker initialization errors
console.log('Date render: Datepicker error:', error);
}
// Use a more aggressive approach - hide buttons with multiple methods
var self = this;
setTimeout(function() {
// Try multiple selectors to find buttons
var $buttons = self.$form ? self.$form.find('.editable-buttons') : $();
if ($buttons.length === 0) {
$buttons = self.$tpl.closest('.editableform').find('.editable-buttons');
}
if ($buttons.length === 0) {
$buttons = self.$tpl.closest('.editable-container').find('.editable-buttons');
}
console.log('Date render: Found buttons:', $buttons.length);
if ($buttons.length > 0) {
$buttons.hide();
$buttons.css('display', 'none');
console.log('Date render: Hidden buttons');
}
}, 100);
//"clear" link
if(this.options.clear) {
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
@@ -178,24 +207,41 @@ $(function(){
},
autosubmit: function() {
// Override default autosubmit behavior for datepicker workflow
// Show buttons only after date selection
this.$input.on('changeDate', $.proxy(function(e) {
console.log('Date changeDate event triggered');
// Hide the datepicker
this.$input.datepicker('hide');
// Show save/cancel buttons after date selection
setTimeout($.proxy(function() {
if (this.options.showbuttons !== false) {
var $buttons = this.$form ? this.$form.find('.editable-buttons') : $();
if ($buttons.length === 0) {
$buttons = this.$tpl.closest('.editableform').find('.editable-buttons');
}
if ($buttons.length === 0) {
$buttons = this.$tpl.closest('.editable-container').find('.editable-buttons');
}
console.log('Date changeDate: Found buttons to show:', $buttons.length);
$buttons.show();
$buttons.css('display', 'inline-block');
}
}, this), 100);
}, this));
// Keep the original click behavior as backup
this.$input.on('mouseup', '.day', function(e){
if($(e.currentTarget).is('.old') || $(e.currentTarget).is('.new')) {
return;
}
console.log('Date mouseup on day');
var $form = $(this).closest('form');
setTimeout(function() {
$form.submit();
$form.find('.editable-buttons').show();
}, 200);
});
//changedate is not suitable as it triggered when showing datepicker. see #149
/*
this.$input.on('changeDate', function(e){
var $form = $(this).closest('form');
setTimeout(function() {
$form.submit();
}, 200);
});
*/
},
/*
@@ -280,4 +326,5 @@ $(function(){
$.fn.editabletypes.date = Date;
}(window.jQuery));
return $;
}

View File

@@ -8,7 +8,7 @@ Automatically shown in inline mode.
@since 1.4.0
**/
(function ($) {
function attachDateField($) {
"use strict";
var DateField = function (options) {
@@ -33,12 +33,36 @@ Automatically shown in inline mode.
//need to disable original event handlers
this.$input.off('focus keydown');
// Hide buttons initially for datepicker workflow
var self = this;
setTimeout(function() {
if (!self.$form) {
// Find buttons in the broader DOM and hide them directly
var $allButtons = $('.editable-buttons:visible');
if ($allButtons.length > 0) {
$allButtons.each(function(i, btn) {
// Directly hide this button for datepicker
var $btn = $(btn);
$btn.hide();
$btn.css('display', 'none !important');
$btn.addClass('datepicker-hidden');
// Store reference for later showing
self.$dateButtons = $btn;
});
}
}
}, 500);
//update value of datepicker
this.$input.keyup($.proxy(function(){
this.$tpl.removeData('date');
this.$tpl.datepicker('update');
}, this));
// Manually call autosubmit to set up our event handlers
this.autosubmit();
},
value2input: function(value) {
@@ -86,7 +110,61 @@ Automatically shown in inline mode.
},
autosubmit: function() {
//reset autosubmit to empty
// Override default autosubmit behavior for datepicker workflow
// We handle this manually with changeDate event
// Setup the manual workflow: show buttons only after date selection
this.$tpl.on('changeDate', $.proxy(function(e) {
// Hide the datepicker using multiple methods to ensure it closes
setTimeout($.proxy(function() {
// Try datepicker hide methods
try {
this.$tpl.datepicker('hide');
} catch(err) {
// Fallback to input method
}
try {
this.$input.datepicker('hide');
} catch(err) {
// Continue to force methods
}
// Force hide all datepicker elements
$('.datepicker').hide();
$('.datepicker-dropdown').hide();
// Ensure any remaining visible datepickers are hidden
var $visiblePicker = $('.datepicker:visible, .datepicker-dropdown:visible');
if ($visiblePicker.length > 0) {
$visiblePicker.css('display', 'none !important');
$visiblePicker.css('visibility', 'hidden');
}
}, this), 10);
// Show save/cancel buttons after date selection
setTimeout($.proxy(function() {
if (this.options.showbuttons !== false) {
var $buttons = this.$dateButtons || $('.editable-buttons.datepicker-hidden');
if ($buttons.length === 0) {
$buttons = this.$form ? this.$form.find('.editable-buttons') : $();
}
if ($buttons.length === 0) {
$buttons = this.$tpl.closest('.editableform').find('.editable-buttons');
}
if ($buttons.length === 0) {
$buttons = this.$tpl.closest('.editable-container').find('.editable-buttons');
}
$buttons.show();
$buttons.css('display', 'inline-flex');
$buttons.addClass('show-buttons');
$buttons.removeClass('datepicker-hidden');
}
}, this), 100);
}, this));
// Do NOT call parent autosubmit to prevent immediate form submission
}
});
@@ -114,4 +192,5 @@ Automatically shown in inline mode.
$.fn.editabletypes.datefield = DateField;
}(window.jQuery));
return $;
}

View File

@@ -4,7 +4,8 @@ List - abstract class for inputs that have source option loaded from js array or
@class list
@extends abstractinput
**/
(function ($) {
function attachList($) {
"use strict";
var List = function (options) {
@@ -331,6 +332,7 @@ List - abstract class for inputs that have source option loaded from js array or
sourceOptions: null
});
$.fn.editabletypes.list = List;
}(window.jQuery));
$.fn.editabletypes.list = List;
return $;
}

View File

@@ -19,7 +19,7 @@ $(function(){
});
</script>
**/
(function ($) {
function attachSelect($) {
"use strict";
var Select = function (options) {
@@ -93,4 +93,5 @@ $(function(){
$.fn.editabletypes.select = Select;
}(window.jQuery));
return $;
}

361
src/inputs/select2/select2.js vendored Normal file
View File

@@ -0,0 +1,361 @@
/**
Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options.
You should manually download and include select2 distributive:
<link href="select2/select2.css" rel="stylesheet" type="text/css"></link>
<script src="select2/select2.js"></script>
To make it **bootstrap-styled** you can use css from [here](https://github.com/t0m/select2-bootstrap-css):
<link href="select2-bootstrap.css" rel="stylesheet" type="text/css"></link>
**Note:** currently `autotext` feature does not work for select2 with `ajax` remote source.
You need initially put both `data-value` and element's text youself:
<a href="#" data-type="select2" data-value="1">Text1</a>
@class select2
@extends abstractinput
@since 1.4.1
@final
@example
<a href="#" id="country" data-type="select2" data-pk="1" data-value="ru" data-url="/post" data-title="Select country"></a>
<script>
$(function(){
//local source
$('#country').editable({
source: [
{id: 'gb', text: 'Great Britain'},
{id: 'us', text: 'United States'},
{id: 'ru', text: 'Russia'}
],
select2: {
multiple: true
}
});
//remote source (simple)
$('#country').editable({
source: '/getCountries',
select2: {
placeholder: 'Select Country',
minimumInputLength: 1
}
});
//remote source (advanced)
$('#country').editable({
select2: {
placeholder: 'Select Country',
allowClear: true,
minimumInputLength: 3,
id: function (item) {
return item.CountryId;
},
ajax: {
url: '/getCountries',
dataType: 'json',
data: function (term, page) {
return { query: term };
},
results: function (data, page) {
return { results: data };
}
},
formatResult: function (item) {
return item.CountryName;
},
formatSelection: function (item) {
return item.CountryName;
},
initSelection: function (element, callback) {
return $.get('/getCountryById', { query: element.val() }, function (data) {
callback(data);
});
}
}
});
});
</script>
**/
function attachSelect2($) {
"use strict";
var Constructor = function (options) {
this.init('select2', options, Constructor.defaults);
options.select2 = options.select2 || {};
this.sourceData = null;
//placeholder
if(options.placeholder) {
options.select2.placeholder = options.placeholder;
}
//if not `tags` mode, use source
if(!options.select2.tags && options.source) {
var source = options.source;
//if source is function, call it (once!)
if (typeof (options.source) === 'function') {
source = options.source.call(options.scope);
}
if (typeof source === 'string') {
options.select2.ajax = options.select2.ajax || {};
//some default ajax params
if(!options.select2.ajax.data) {
options.select2.ajax.data = function(term) {return { query:term };};
}
if(!options.select2.ajax.results) {
options.select2.ajax.results = function(data) { return {results:data };};
}
options.select2.ajax.url = source;
} else {
//check format and convert x-editable format to select2 format (if needed)
this.sourceData = this.convertSource(source);
options.select2.data = this.sourceData;
}
}
//overriding objects in config (as by default jQuery extend() is not recursive)
this.options.select2 = $.extend({}, Constructor.defaults.select2, options.select2);
//detect whether it is multi-valued
this.isMultiple = this.options.select2.tags || this.options.select2.multiple;
this.isRemote = ('ajax' in this.options.select2);
//store function returning ID of item
//should be here as used inautotext for local source
this.idFunc = this.options.select2.id;
if (typeof(this.idFunc) !== "function") {
var idKey = this.idFunc || 'id';
this.idFunc = function (e) { return e[idKey]; };
}
//store function that renders text in select2
this.formatSelection = this.options.select2.formatSelection;
if (typeof(this.formatSelection) !== "function") {
this.formatSelection = function (e) { return e.text; };
}
};
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
$.extend(Constructor.prototype, {
render: function() {
this.setClass();
//can not apply select2 here as it calls initSelection
//over input that does not have correct value yet.
//apply select2 only in value2input
//this.$input.select2(this.options.select2);
//when data is loaded via ajax, we need to know when it's done to populate listData
if(this.isRemote) {
//listen to loaded event to populate data
this.$input.on('select2-loaded', $.proxy(function(e) {
this.sourceData = e.items.results;
}, this));
}
//trigger resize of editableform to re-position container in multi-valued mode
if(this.isMultiple) {
this.$input.on('change', function() {
$(this).closest('form').parent().triggerHandler('resize');
});
}
// Fix for Select2 v4.1.0 - manually update value when selection is made
// This fixes the issue where select2:select event fires but the value doesn't update
this.$input.on('select2:select', function(e) {
if (e.params && e.params.data && e.params.data.id !== undefined) {
$(this).val(e.params.data.id);
$(this).trigger('change.select2');
}
});
},
value2html: function(value, element) {
var text = '', data,
that = this;
if(this.options.select2.tags) { //in tags mode just assign value
data = value;
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
} else if(this.sourceData) {
data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
} else {
//can not get list of possible values
//(e.g. autotext for select2 with ajax source)
}
//data may be array (when multiple values allowed)
if(Array.isArray(data)) {
//collect selected data and show with separator
text = [];
$.each(data, function(k, v){
text.push(v && typeof v === 'object' ? that.formatSelection(v) : v);
});
} else if(data) {
text = that.formatSelection(data);
}
text = Array.isArray(text) ? text.join(this.options.viewseparator) : text;
//$(element).text(text);
Constructor.superclass.value2html.call(this, text, element);
},
html2value: function(html) {
return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null;
},
value2input: function(value) {
// if value array => join it anyway
if(Array.isArray(value)) {
value = value.join(this.getSeparator());
}
//for remote source just set value, text is updated by initSelection
if(!this.$input.data('select2')) {
this.$input.val(value);
this.$input.select2(this.options.select2);
} else {
//Use select2's proper API to set the value instead of just the hidden input
// Try Select2 v4 API - first set the value, then trigger change
this.$input.val(value);
this.$input.trigger('change.select2');
//second argument needed to separate initial change from user's click (for autosubmit)
this.$input.trigger('change', true);
}
// if defined remote source AND no multiple mode AND no user's initSelection provided -->
// we should somehow get text for provided id.
// The solution is to use element's text as text for that id (exclude empty)
if(this.isRemote && !this.isMultiple && !this.options.select2.initSelection) {
// customId and customText are methods to extract `id` and `text` from data object
// we can use this workaround only if user did not define these methods
// otherwise we cant construct data object
var customId = this.options.select2.id,
customText = this.options.select2.formatSelection;
if(!customId && !customText) {
var $el = $(this.options.scope);
if (!$el.data('editable').isEmpty) {
var data = {id: value, text: $el.text()};
this.$input.select2('data', data);
}
}
}
},
input2value: function() {
return this.$input.select2('val');
},
str2value: function(str, separator) {
if(typeof str !== 'string' || !this.isMultiple) {
return str;
}
separator = separator || this.getSeparator();
var val, i, l;
if (str === null || str.length < 1) {
return null;
}
val = str.split(separator);
for (i = 0, l = val.length; i < l; i = i + 1) {
val[i] = val[i].trim();
}
return val;
},
autosubmit: function() {
this.$input.on('change', function(e, isInitial){
if(!isInitial) {
$(this).closest('form').submit();
}
});
},
getSeparator: function() {
return this.options.select2.separator || $.fn.select2.defaults.separator;
},
/*
Converts source from x-editable format: {value: 1, text: "1"} to
select2 format: {id: 1, text: "1"}
*/
convertSource: function(source) {
if(Array.isArray(source) && source.length && source[0].value !== undefined) {
for(var i = 0; i<source.length; i++) {
if(source[i].value !== undefined) {
source[i].id = source[i].value;
delete source[i].value;
}
}
}
return source;
},
destroy: function() {
if(this.$input) {
if(this.$input.data('select2')) {
this.$input.select2('destroy');
}
}
}
});
Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
/**
@property tpl
@default <input type="hidden">
**/
tpl:'<input type="hidden">',
/**
Configuration of select2. [Full list of options](http://ivaynberg.github.com/select2).
@property select2
@type object
@default null
**/
select2: null,
/**
Placeholder attribute of select
@property placeholder
@type string
@default null
**/
placeholder: null,
/**
Source data for select. It will be assigned to select2 `data` property and kept here just for convenience.
Please note, that format is different from simple `select` input: use 'id' instead of 'value'.
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
@property source
@type array|string|function
@default null
**/
source: null,
/**
Separator used to display tags.
@property viewseparator
@type string
@default ', '
**/
viewseparator: ', '
});
$.fn.editabletypes.select2 = Constructor;
return $;
}

View File

@@ -15,7 +15,7 @@ $(function(){
});
</script>
**/
(function ($) {
function attachText($) {
"use strict";
var Text = function (options) {
@@ -131,4 +131,5 @@ $(function(){
$.fn.editabletypes.text = Text;
}(window.jQuery));
return $;
}

View File

@@ -16,7 +16,7 @@ $(function(){
});
</script>
**/
(function ($) {
function attachTextarea($) {
"use strict";
var Textarea = function (options) {
@@ -108,4 +108,5 @@ $(function(){
$.fn.editabletypes.textarea = Textarea;
}(window.jQuery));
return $;
}

14
src/umd-wrapper.js Normal file
View File

@@ -0,0 +1,14 @@
// UMD Wrapper for x-editable that auto-initializes with jQuery
import initializeXEditable from './bootstrap5-editable.js';
// The UMD pattern expects a factory function that receives dependencies
// This wrapper will be called by webpack's UMD template with jQuery as parameter
export default function xEditableFactory($) {
// Auto-initialize when called by UMD
if ($ && $.fn) {
return initializeXEditable($);
} else {
// Return the init function for manual use
return initializeXEditable;
}
}

1
test-types.js Normal file
View File

@@ -0,0 +1 @@
console.log('Available input types:', Object.keys($.fn.editabletypes));

View File

@@ -3,21 +3,21 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");
module.exports = [
// Main bundle (jQuery, Bootstrap, App)
// Demo bundle (for demo only, not part of the library)
{
entry: {
jquery: "jquery",
app: "./demo/demo.js",
},
output: {
path: path.resolve(__dirname, "dist"), // Place them directly in dist/
filename: "[name].js", // app.js, jquery.js, bootstrap.js
path: path.resolve(__dirname, "demo/dist"), // Place in demo/dist folder
filename: "[name].js", // app.js
clean: true // Clean the demo/dist directory before emit
},
resolve: {
alias: {
jquery: path.resolve(__dirname, "node_modules/jquery"),
bootstrap: path.resolve(__dirname, "node_modules/bootstrap"),
"bootstrap5-editable": path.resolve(__dirname, "dist/bootstrap5-editable")
dist: path.resolve(__dirname, "dist")
}
},
module: {
@@ -34,34 +34,34 @@ module.exports = [
}
}
]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
bootstrap: "bootstrap",
"window.bootstrap": "bootstrap"
}),
new CopyWebpackPlugin({
patterns: [
{ from: "src/editable-form/editable-form.css", to: path.resolve(__dirname, "dist/bootstrap5-editable/css") },
{ from: "node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css", to: path.resolve(__dirname, "dist/bootstrap5-editable/css") },
{ from: "node_modules/bootstrap-icons/font/fonts", to: path.resolve(__dirname, "dist/fonts") }
]
})
]
}
},
// X-Editable Plugin (Bootstrap 5)
{
entry: "./src/bootstrap5-editable.js",
output: {
path: path.resolve(__dirname, "dist/bootstrap5-editable/js"), // X-Editable stays here
path: path.resolve(__dirname, "dist/bootstrap5-editable/js"),
filename: "bootstrap-editable.js",
library: {
name: "EditableForm",
type: "umd"
},
globalObject: "this",
clean: true // Clean the output directory before emit
},
externals: {
jquery: {
commonjs: "jquery",
commonjs2: "jquery",
amd: "jquery",
root: "jQuery"
},
bootstrap: {
commonjs: "bootstrap",
commonjs2: "bootstrap",
amd: "bootstrap",
root: "bootstrap"
}
},
resolve: {
@@ -69,6 +69,28 @@ module.exports = [
jquery: path.resolve(__dirname, "node_modules/jquery"),
bootstrap: path.resolve(__dirname, "node_modules/bootstrap")
}
}
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: "src/editable-form/editable-form.css",
to: path.resolve(__dirname, "dist/bootstrap5-editable/css/bootstrap-editable.css")
},
{
from: "src/img",
to: path.resolve(__dirname, "dist/bootstrap5-editable/img")
}
]
})
]
}
];

35
webpack.demo.js Normal file
View File

@@ -0,0 +1,35 @@
const path = require("path");
// Demo bundle (for demo only, not part of the library)
module.exports = {
entry: {
app: "./demo/demo.js",
},
output: {
path: path.resolve(__dirname, "demo/dist"), // Place in demo/dist folder
filename: "[name].js", // app.js
clean: true // Clean the demo/dist directory before emit
},
resolve: {
alias: {
jquery: path.resolve(__dirname, "node_modules/jquery"),
bootstrap: path.resolve(__dirname, "node_modules/bootstrap"),
dist: path.resolve(__dirname, "dist")
}
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
type: "asset/resource",
generator: {
filename: "fonts/[name][ext]"
}
}
]
}
};

68
webpack.lib.js Normal file
View File

@@ -0,0 +1,68 @@
const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");
// X-Editable Plugin (Bootstrap 5) - Library build only
module.exports = {
entry: "./src/umd-wrapper.js",
output: {
path: path.resolve(__dirname, "dist/bootstrap5-editable/js"),
filename: "bootstrap-editable.js",
library: {
name: "EditableForm",
type: "umd",
export: 'default'
},
globalObject: "this",
clean: true, // Clean the output directory before emit
// Custom UMD template that auto-calls the exported function with jQuery
auxiliaryComment: {
root: "X-Editable Bootstrap 5 - Auto-initializing UMD Bundle",
commonjs: "X-Editable Bootstrap 5 - CommonJS",
commonjs2: "X-Editable Bootstrap 5 - CommonJS2",
amd: "X-Editable Bootstrap 5 - AMD"
}
},
externals: {
jquery: {
commonjs: "jquery",
commonjs2: "jquery",
amd: "jquery",
root: "jQuery"
},
bootstrap: {
commonjs: "bootstrap",
commonjs2: "bootstrap",
amd: "bootstrap",
root: "bootstrap"
}
},
resolve: {
alias: {
jquery: path.resolve(__dirname, "node_modules/jquery"),
bootstrap: path.resolve(__dirname, "node_modules/bootstrap")
}
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: "src/editable-form/editable-form.css",
to: path.resolve(__dirname, "dist/bootstrap5-editable/css/bootstrap-editable.css")
},
{
from: "src/img",
to: path.resolve(__dirname, "dist/bootstrap5-editable/img")
}
]
})
]
};