x-editable-rails 1.5.1 → 1.5.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -13
- data/lib/x-editable-rails/version.rb +2 -2
- data/lib/x-editable-rails/view_helpers.rb +66 -41
- data/vendor/assets/javascripts/editable/bootstrap-editable.js +336 -203
- data/vendor/assets/javascripts/editable/bootstrap2-editable.js +308 -202
- data/vendor/assets/javascripts/editable/inputs-ext/wysihtml5-editable.js +9 -1
- data/vendor/assets/javascripts/editable/jquery-editable-poshytip.js +315 -202
- data/vendor/assets/javascripts/editable/jqueryui-editable.js +316 -203
- data/vendor/assets/javascripts/editable/rails/editable_form.js.coffee +14 -18
- data/vendor/assets/javascripts/editable/rails/error_handling.js.coffee +4 -0
- data/vendor/assets/javascripts/editable/rails.js.coffee +2 -1
- data/vendor/assets/stylesheets/editable/bootstrap-editable.scss +25 -25
- data/vendor/assets/stylesheets/editable/bootstrap2-editable.scss +25 -25
- metadata +19 -32
- /data/vendor/assets/stylesheets/editable/inputs-ext/{bootstrap-typehead.css → bootstrap-typeahead.css} +0 -0
@@ -1,7 +1,7 @@
|
|
1
|
-
/*! X-editable - v1.5.
|
2
|
-
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
3
|
-
* http://github.com/vitalets/x-editable
|
4
|
-
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
1
|
+
/*! X-editable - v1.5.1
|
2
|
+
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
3
|
+
* http://github.com/vitalets/x-editable
|
4
|
+
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
5
5
|
/**
|
6
6
|
Form with single input element, two buttons and two states: normal/loading.
|
7
7
|
Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
|
@@ -185,7 +185,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
185
185
|
} else {
|
186
186
|
//convert newline to <br> for more pretty error display
|
187
187
|
if(msg) {
|
188
|
-
lines = msg.split(
|
188
|
+
lines = (''+msg).split('\n');
|
189
189
|
for (var i = 0; i < lines.length; i++) {
|
190
190
|
lines[i] = $('<div>').text(lines[i]).html();
|
191
191
|
}
|
@@ -200,11 +200,21 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
200
200
|
e.stopPropagation();
|
201
201
|
e.preventDefault();
|
202
202
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
//validation
|
207
|
-
if
|
203
|
+
//get new value from input
|
204
|
+
var newValue = this.input.input2value();
|
205
|
+
|
206
|
+
//validation: if validate returns string or truthy value - means error
|
207
|
+
//if returns object like {newValue: '...'} => submitted value is reassigned to it
|
208
|
+
var error = this.validate(newValue);
|
209
|
+
if ($.type(error) === 'object' && error.newValue !== undefined) {
|
210
|
+
newValue = error.newValue;
|
211
|
+
this.input.value2input(newValue);
|
212
|
+
if(typeof error.msg === 'string') {
|
213
|
+
this.error(error.msg);
|
214
|
+
this.showForm();
|
215
|
+
return;
|
216
|
+
}
|
217
|
+
} else if (error) {
|
208
218
|
this.error(error);
|
209
219
|
this.showForm();
|
210
220
|
return;
|
@@ -503,6 +513,8 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
503
513
|
send: 'auto',
|
504
514
|
/**
|
505
515
|
Function for client-side validation. If returns string - means validation not passed and string showed as error.
|
516
|
+
Since 1.5.1 you can modify submitted value by returning object from `validate`:
|
517
|
+
`{newValue: '...'}` or `{newValue: '...', msg: '...'}`
|
506
518
|
|
507
519
|
@property validate
|
508
520
|
@type function
|
@@ -625,7 +637,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
625
637
|
//engine
|
626
638
|
$.fn.editableform.engine = 'jquery';
|
627
639
|
}(window.jQuery));
|
628
|
-
|
640
|
+
|
629
641
|
/**
|
630
642
|
* EditableForm utilites
|
631
643
|
*/
|
@@ -875,7 +887,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
875
887
|
|
876
888
|
};
|
877
889
|
}(window.jQuery));
|
878
|
-
|
890
|
+
|
879
891
|
/**
|
880
892
|
Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br>
|
881
893
|
This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br>
|
@@ -1391,7 +1403,7 @@ Applied as jQuery method.
|
|
1391
1403
|
};
|
1392
1404
|
|
1393
1405
|
}(window.jQuery));
|
1394
|
-
|
1406
|
+
|
1395
1407
|
/**
|
1396
1408
|
* Editable Inline
|
1397
1409
|
* ---------------------
|
@@ -1445,7 +1457,7 @@ Applied as jQuery method.
|
|
1445
1457
|
}
|
1446
1458
|
});
|
1447
1459
|
|
1448
|
-
}(window.jQuery));
|
1460
|
+
}(window.jQuery));
|
1449
1461
|
/**
|
1450
1462
|
Makes editable any HTML element on the page. Applied as jQuery method.
|
1451
1463
|
|
@@ -2015,7 +2027,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
2015
2027
|
/**
|
2016
2028
|
This method collects values from several editable elements and submit them all to server.
|
2017
2029
|
Internally it runs client-side validation for all fields and submits only in case of success.
|
2018
|
-
See <a href="#newrecord">creating new records</a> for details.
|
2030
|
+
See <a href="#newrecord">creating new records</a> for details.
|
2031
|
+
Since 1.5.1 `submit` can be applied to single element to send data programmatically. In that case
|
2032
|
+
`url`, `success` and `error` is taken from initial options and you can just call `$('#username').editable('submit')`.
|
2019
2033
|
|
2020
2034
|
@method submit(options)
|
2021
2035
|
@param {object} options
|
@@ -2029,31 +2043,76 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
2029
2043
|
case 'submit': //collects value, validate and submit to server for creating new record
|
2030
2044
|
var config = arguments[1] || {},
|
2031
2045
|
$elems = this,
|
2032
|
-
errors = this.editable('validate')
|
2033
|
-
values;
|
2046
|
+
errors = this.editable('validate');
|
2034
2047
|
|
2048
|
+
// validation ok
|
2035
2049
|
if($.isEmptyObject(errors)) {
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2050
|
+
var ajaxOptions = {};
|
2051
|
+
|
2052
|
+
// for single element use url, success etc from options
|
2053
|
+
if($elems.length === 1) {
|
2054
|
+
var editable = $elems.data('editable');
|
2055
|
+
//standard params
|
2056
|
+
var params = {
|
2057
|
+
name: editable.options.name || '',
|
2058
|
+
value: editable.input.value2submit(editable.value),
|
2059
|
+
pk: (typeof editable.options.pk === 'function') ?
|
2060
|
+
editable.options.pk.call(editable.options.scope) :
|
2061
|
+
editable.options.pk
|
2062
|
+
};
|
2063
|
+
|
2064
|
+
//additional params
|
2065
|
+
if(typeof editable.options.params === 'function') {
|
2066
|
+
params = editable.options.params.call(editable.options.scope, params);
|
2067
|
+
} else {
|
2068
|
+
//try parse json in single quotes (from data-params attribute)
|
2069
|
+
editable.options.params = $.fn.editableutils.tryParseJson(editable.options.params, true);
|
2070
|
+
$.extend(params, editable.options.params);
|
2071
|
+
}
|
2072
|
+
|
2073
|
+
ajaxOptions = {
|
2074
|
+
url: editable.options.url,
|
2075
|
+
data: params,
|
2076
|
+
type: 'POST'
|
2077
|
+
};
|
2078
|
+
|
2079
|
+
// use success / error from options
|
2080
|
+
config.success = config.success || editable.options.success;
|
2081
|
+
config.error = config.error || editable.options.error;
|
2082
|
+
|
2083
|
+
// multiple elements
|
2084
|
+
} else {
|
2085
|
+
var values = this.editable('getValue');
|
2086
|
+
|
2087
|
+
ajaxOptions = {
|
2088
|
+
url: config.url,
|
2089
|
+
data: values,
|
2090
|
+
type: 'POST'
|
2091
|
+
};
|
2039
2092
|
}
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
data: values,
|
2044
|
-
type: 'POST'
|
2045
|
-
}, config.ajaxOptions))
|
2046
|
-
.success(function(response) {
|
2047
|
-
//successful response 200 OK
|
2048
|
-
if(typeof config.success === 'function') {
|
2093
|
+
|
2094
|
+
// ajax success callabck (response 200 OK)
|
2095
|
+
ajaxOptions.success = typeof config.success === 'function' ? function(response) {
|
2049
2096
|
config.success.call($elems, response, config);
|
2050
|
-
}
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
}
|
2056
|
-
|
2097
|
+
} : $.noop;
|
2098
|
+
|
2099
|
+
// ajax error callabck
|
2100
|
+
ajaxOptions.error = typeof config.error === 'function' ? function() {
|
2101
|
+
config.error.apply($elems, arguments);
|
2102
|
+
} : $.noop;
|
2103
|
+
|
2104
|
+
// extend ajaxOptions
|
2105
|
+
if(config.ajaxOptions) {
|
2106
|
+
$.extend(ajaxOptions, config.ajaxOptions);
|
2107
|
+
}
|
2108
|
+
|
2109
|
+
// extra data
|
2110
|
+
if(config.data) {
|
2111
|
+
$.extend(ajaxOptions.data, config.data);
|
2112
|
+
}
|
2113
|
+
|
2114
|
+
// perform ajax request
|
2115
|
+
$.ajax(ajaxOptions);
|
2057
2116
|
} else { //client-side validation error
|
2058
2117
|
if(typeof config.error === 'function') {
|
2059
2118
|
config.error.call($elems, errors);
|
@@ -2257,7 +2316,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
2257
2316
|
};
|
2258
2317
|
|
2259
2318
|
}(window.jQuery));
|
2260
|
-
|
2319
|
+
|
2261
2320
|
/**
|
2262
2321
|
AbstractInput - base class for all editable inputs.
|
2263
2322
|
It defines interface to be implemented by any input type.
|
@@ -2478,7 +2537,7 @@ To create your own input you can inherit from this class.
|
|
2478
2537
|
$.extend($.fn.editabletypes, {abstractinput: AbstractInput});
|
2479
2538
|
|
2480
2539
|
}(window.jQuery));
|
2481
|
-
|
2540
|
+
|
2482
2541
|
/**
|
2483
2542
|
List - abstract class for inputs that have source option loaded from js array or via ajax
|
2484
2543
|
|
@@ -2814,7 +2873,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2814
2873
|
$.fn.editabletypes.list = List;
|
2815
2874
|
|
2816
2875
|
}(window.jQuery));
|
2817
|
-
|
2876
|
+
|
2818
2877
|
/**
|
2819
2878
|
Text input
|
2820
2879
|
|
@@ -2949,7 +3008,7 @@ $(function(){
|
|
2949
3008
|
$.fn.editabletypes.text = Text;
|
2950
3009
|
|
2951
3010
|
}(window.jQuery));
|
2952
|
-
|
3011
|
+
|
2953
3012
|
/**
|
2954
3013
|
Textarea input
|
2955
3014
|
|
@@ -3061,7 +3120,7 @@ $(function(){
|
|
3061
3120
|
$.fn.editabletypes.textarea = Textarea;
|
3062
3121
|
|
3063
3122
|
}(window.jQuery));
|
3064
|
-
|
3123
|
+
|
3065
3124
|
/**
|
3066
3125
|
Select (dropdown)
|
3067
3126
|
|
@@ -3158,7 +3217,7 @@ $(function(){
|
|
3158
3217
|
$.fn.editabletypes.select = Select;
|
3159
3218
|
|
3160
3219
|
}(window.jQuery));
|
3161
|
-
|
3220
|
+
|
3162
3221
|
/**
|
3163
3222
|
List of checkboxes.
|
3164
3223
|
Internally value stored as javascript array of values.
|
@@ -3315,7 +3374,7 @@ $(function(){
|
|
3315
3374
|
$.fn.editabletypes.checklist = Checklist;
|
3316
3375
|
|
3317
3376
|
}(window.jQuery));
|
3318
|
-
|
3377
|
+
|
3319
3378
|
/**
|
3320
3379
|
HTML5 input types.
|
3321
3380
|
Following types are supported:
|
@@ -3534,7 +3593,7 @@ Time
|
|
3534
3593
|
});
|
3535
3594
|
$.fn.editabletypes.time = Time;
|
3536
3595
|
}(window.jQuery));
|
3537
|
-
|
3596
|
+
|
3538
3597
|
/**
|
3539
3598
|
Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
|
3540
3599
|
Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options.
|
@@ -3575,7 +3634,11 @@ $(function(){
|
|
3575
3634
|
});
|
3576
3635
|
//remote source (simple)
|
3577
3636
|
$('#country').editable({
|
3578
|
-
source: '/getCountries'
|
3637
|
+
source: '/getCountries',
|
3638
|
+
select2: {
|
3639
|
+
placeholder: 'Select Country',
|
3640
|
+
minimumInputLength: 1
|
3641
|
+
}
|
3579
3642
|
});
|
3580
3643
|
//remote source (advanced)
|
3581
3644
|
$('#country').editable({
|
@@ -3651,14 +3714,14 @@ $(function(){
|
|
3651
3714
|
options.select2.data = this.sourceData;
|
3652
3715
|
}
|
3653
3716
|
}
|
3654
|
-
|
3717
|
+
|
3655
3718
|
//overriding objects in config (as by default jQuery extend() is not recursive)
|
3656
3719
|
this.options.select2 = $.extend({}, Constructor.defaults.select2, options.select2);
|
3657
|
-
|
3720
|
+
|
3658
3721
|
//detect whether it is multi-valued
|
3659
3722
|
this.isMultiple = this.options.select2.tags || this.options.select2.multiple;
|
3660
3723
|
this.isRemote = ('ajax' in this.options.select2);
|
3661
|
-
|
3724
|
+
|
3662
3725
|
//store function returning ID of item
|
3663
3726
|
//should be here as used inautotext for local source
|
3664
3727
|
this.idFunc = this.options.select2.id;
|
@@ -3666,12 +3729,12 @@ $(function(){
|
|
3666
3729
|
var idKey = this.idFunc || 'id';
|
3667
3730
|
this.idFunc = function (e) { return e[idKey]; };
|
3668
3731
|
}
|
3669
|
-
|
3732
|
+
|
3670
3733
|
//store function that renders text in select2
|
3671
|
-
this.formatSelection = this.options.select2.formatSelection;
|
3734
|
+
this.formatSelection = this.options.select2.formatSelection;
|
3672
3735
|
if (typeof(this.formatSelection) !== "function") {
|
3673
3736
|
this.formatSelection = function (e) { return e.text; };
|
3674
|
-
}
|
3737
|
+
}
|
3675
3738
|
};
|
3676
3739
|
|
3677
3740
|
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
|
@@ -3693,61 +3756,55 @@ $(function(){
|
|
3693
3756
|
}, this));
|
3694
3757
|
}
|
3695
3758
|
|
3696
|
-
//trigger resize of editableform to re-position container in multi-valued mode
|
3759
|
+
//trigger resize of editableform to re-position container in multi-valued mode
|
3697
3760
|
if(this.isMultiple) {
|
3698
3761
|
this.$input.on('change', function() {
|
3699
3762
|
$(this).closest('form').parent().triggerHandler('resize');
|
3700
|
-
});
|
3763
|
+
});
|
3701
3764
|
}
|
3702
3765
|
},
|
3703
|
-
|
3766
|
+
|
3704
3767
|
value2html: function(value, element) {
|
3705
3768
|
var text = '', data,
|
3706
3769
|
that = this;
|
3707
|
-
|
3770
|
+
|
3708
3771
|
if(this.options.select2.tags) { //in tags mode just assign value
|
3709
3772
|
data = value;
|
3710
|
-
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
|
3773
|
+
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
|
3711
3774
|
} else if(this.sourceData) {
|
3712
3775
|
data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
|
3713
3776
|
} else {
|
3714
3777
|
//can not get list of possible values
|
3715
|
-
//(e.g. autotext for select2 with ajax source)
|
3778
|
+
//(e.g. autotext for select2 with ajax source)
|
3716
3779
|
}
|
3717
|
-
|
3718
|
-
//data may be array (when multiple values allowed)
|
3780
|
+
|
3781
|
+
//data may be array (when multiple values allowed)
|
3719
3782
|
if($.isArray(data)) {
|
3720
3783
|
//collect selected data and show with separator
|
3721
3784
|
text = [];
|
3722
3785
|
$.each(data, function(k, v){
|
3723
|
-
text.push(v && typeof v === 'object' ? that.formatSelection(v) : v);
|
3724
|
-
});
|
3786
|
+
text.push(v && typeof v === 'object' ? that.formatSelection(v) : v);
|
3787
|
+
});
|
3725
3788
|
} else if(data) {
|
3726
|
-
text = that.formatSelection(data);
|
3789
|
+
text = that.formatSelection(data);
|
3727
3790
|
}
|
3728
3791
|
|
3729
3792
|
text = $.isArray(text) ? text.join(this.options.viewseparator) : text;
|
3730
3793
|
|
3731
3794
|
//$(element).text(text);
|
3732
3795
|
Constructor.superclass.value2html.call(this, text, element);
|
3733
|
-
},
|
3734
|
-
|
3796
|
+
},
|
3797
|
+
|
3735
3798
|
html2value: function(html) {
|
3736
3799
|
return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null;
|
3737
|
-
},
|
3738
|
-
|
3800
|
+
},
|
3801
|
+
|
3739
3802
|
value2input: function(value) {
|
3740
|
-
//
|
3741
|
-
|
3742
|
-
|
3743
|
-
|
3744
|
-
|
3745
|
-
this.$input.select2('data', items[0]);
|
3746
|
-
return;
|
3747
|
-
}
|
3748
|
-
}
|
3749
|
-
*/
|
3750
|
-
|
3803
|
+
// if value array => join it anyway
|
3804
|
+
if($.isArray(value)) {
|
3805
|
+
value = value.join(this.getSeparator());
|
3806
|
+
}
|
3807
|
+
|
3751
3808
|
//for remote source just set value, text is updated by initSelection
|
3752
3809
|
if(!this.$input.data('select2')) {
|
3753
3810
|
this.$input.val(value);
|
@@ -3755,15 +3812,27 @@ $(function(){
|
|
3755
3812
|
} else {
|
3756
3813
|
//second argument needed to separate initial change from user's click (for autosubmit)
|
3757
3814
|
this.$input.val(value).trigger('change', true);
|
3815
|
+
|
3816
|
+
//Uncaught Error: cannot call val() if initSelection() is not defined
|
3817
|
+
//this.$input.select2('val', value);
|
3758
3818
|
}
|
3759
|
-
|
3760
|
-
//if remote source AND no user's initSelection provided -->
|
3819
|
+
|
3820
|
+
// if defined remote source AND no multiple mode AND no user's initSelection provided -->
|
3821
|
+
// we should somehow get text for provided id.
|
3822
|
+
// The solution is to use element's text as text for that id (exclude empty)
|
3761
3823
|
if(this.isRemote && !this.isMultiple && !this.options.select2.initSelection) {
|
3824
|
+
// customId and customText are methods to extract `id` and `text` from data object
|
3825
|
+
// we can use this workaround only if user did not define these methods
|
3826
|
+
// otherwise we cant construct data object
|
3762
3827
|
var customId = this.options.select2.id,
|
3763
3828
|
customText = this.options.select2.formatSelection;
|
3764
|
-
|
3765
|
-
|
3766
|
-
this
|
3829
|
+
|
3830
|
+
if(!customId && !customText) {
|
3831
|
+
var $el = $(this.options.scope);
|
3832
|
+
if (!$el.data('editable').isEmpty) {
|
3833
|
+
var data = {id: value, text: $el.text()};
|
3834
|
+
this.$input.select2('data', data);
|
3835
|
+
}
|
3767
3836
|
}
|
3768
3837
|
}
|
3769
3838
|
},
|
@@ -3776,11 +3845,11 @@ $(function(){
|
|
3776
3845
|
if(typeof str !== 'string' || !this.isMultiple) {
|
3777
3846
|
return str;
|
3778
3847
|
}
|
3779
|
-
|
3780
|
-
separator = separator || this.
|
3781
|
-
|
3848
|
+
|
3849
|
+
separator = separator || this.getSeparator();
|
3850
|
+
|
3782
3851
|
var val, i, l;
|
3783
|
-
|
3852
|
+
|
3784
3853
|
if (str === null || str.length < 1) {
|
3785
3854
|
return null;
|
3786
3855
|
}
|
@@ -3788,10 +3857,10 @@ $(function(){
|
|
3788
3857
|
for (i = 0, l = val.length; i < l; i = i + 1) {
|
3789
3858
|
val[i] = $.trim(val[i]);
|
3790
3859
|
}
|
3791
|
-
|
3860
|
+
|
3792
3861
|
return val;
|
3793
3862
|
},
|
3794
|
-
|
3863
|
+
|
3795
3864
|
autosubmit: function() {
|
3796
3865
|
this.$input.on('change', function(e, isInitial){
|
3797
3866
|
if(!isInitial) {
|
@@ -3799,7 +3868,11 @@ $(function(){
|
|
3799
3868
|
}
|
3800
3869
|
});
|
3801
3870
|
},
|
3802
|
-
|
3871
|
+
|
3872
|
+
getSeparator: function() {
|
3873
|
+
return this.options.select2.separator || $.fn.select2.defaults.separator;
|
3874
|
+
},
|
3875
|
+
|
3803
3876
|
/*
|
3804
3877
|
Converts source from x-editable format: {value: 1, text: "1"} to
|
3805
3878
|
select2 format: {id: 1, text: "1"}
|
@@ -3813,26 +3886,26 @@ $(function(){
|
|
3813
3886
|
}
|
3814
3887
|
}
|
3815
3888
|
}
|
3816
|
-
return source;
|
3889
|
+
return source;
|
3817
3890
|
},
|
3818
3891
|
|
3819
3892
|
destroy: function() {
|
3820
3893
|
if(this.$input.data('select2')) {
|
3821
3894
|
this.$input.select2('destroy');
|
3822
3895
|
}
|
3823
|
-
}
|
3896
|
+
}
|
3824
3897
|
|
3825
|
-
});
|
3898
|
+
});
|
3826
3899
|
|
3827
3900
|
Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
3828
3901
|
/**
|
3829
3902
|
@property tpl
|
3830
3903
|
@default <input type="hidden">
|
3831
|
-
**/
|
3904
|
+
**/
|
3832
3905
|
tpl:'<input type="hidden">',
|
3833
3906
|
/**
|
3834
3907
|
Configuration of select2. [Full list of options](http://ivaynberg.github.com/select2).
|
3835
|
-
|
3908
|
+
|
3836
3909
|
@property select2
|
3837
3910
|
@type object
|
3838
3911
|
@default null
|
@@ -3844,21 +3917,21 @@ $(function(){
|
|
3844
3917
|
@property placeholder
|
3845
3918
|
@type string
|
3846
3919
|
@default null
|
3847
|
-
**/
|
3920
|
+
**/
|
3848
3921
|
placeholder: null,
|
3849
3922
|
/**
|
3850
3923
|
Source data for select. It will be assigned to select2 `data` property and kept here just for convenience.
|
3851
3924
|
Please note, that format is different from simple `select` input: use 'id' instead of 'value'.
|
3852
|
-
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
|
3853
|
-
|
3925
|
+
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
|
3926
|
+
|
3854
3927
|
@property source
|
3855
3928
|
@type array|string|function
|
3856
3929
|
@default null
|
3857
3930
|
**/
|
3858
3931
|
source: null,
|
3859
3932
|
/**
|
3860
|
-
Separator used to display tags.
|
3861
|
-
|
3933
|
+
Separator used to display tags.
|
3934
|
+
|
3862
3935
|
@property viewseparator
|
3863
3936
|
@type string
|
3864
3937
|
@default ', '
|
@@ -3866,16 +3939,16 @@ $(function(){
|
|
3866
3939
|
viewseparator: ', '
|
3867
3940
|
});
|
3868
3941
|
|
3869
|
-
$.fn.editabletypes.select2 = Constructor;
|
3870
|
-
|
3942
|
+
$.fn.editabletypes.select2 = Constructor;
|
3943
|
+
|
3871
3944
|
}(window.jQuery));
|
3872
|
-
|
3945
|
+
|
3873
3946
|
/**
|
3874
|
-
* Combodate - 1.0.
|
3947
|
+
* Combodate - 1.0.5
|
3875
3948
|
* Dropdown date and time picker.
|
3876
3949
|
* Converts text input into dropdowns to pick day, month, year, hour, minute and second.
|
3877
3950
|
* Uses momentjs as datetime library http://momentjs.com.
|
3878
|
-
* For
|
3951
|
+
* For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang
|
3879
3952
|
*
|
3880
3953
|
* Confusion at noon and midnight - see http://en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight
|
3881
3954
|
* In combodate:
|
@@ -3922,16 +3995,22 @@ $(function(){
|
|
3922
3995
|
this.initCombos();
|
3923
3996
|
|
3924
3997
|
//update original input on change
|
3925
|
-
this.$widget.on('change', 'select', $.proxy(function(){
|
3926
|
-
this.$element.val(this.getValue());
|
3998
|
+
this.$widget.on('change', 'select', $.proxy(function(e) {
|
3999
|
+
this.$element.val(this.getValue()).change();
|
4000
|
+
// update days count if month or year changes
|
4001
|
+
if (this.options.smartDays) {
|
4002
|
+
if ($(e.target).is('.month') || $(e.target).is('.year')) {
|
4003
|
+
this.fillCombo('day');
|
4004
|
+
}
|
4005
|
+
}
|
3927
4006
|
}, this));
|
3928
4007
|
|
3929
4008
|
this.$widget.find('select').css('width', 'auto');
|
3930
4009
|
|
3931
|
-
//hide original input and insert widget
|
4010
|
+
// hide original input and insert widget
|
3932
4011
|
this.$element.hide().after(this.$widget);
|
3933
4012
|
|
3934
|
-
//set initial value
|
4013
|
+
// set initial value
|
3935
4014
|
this.setValue(this.$element.val() || this.options.value);
|
3936
4015
|
},
|
3937
4016
|
|
@@ -3968,22 +4047,41 @@ $(function(){
|
|
3968
4047
|
Initialize combos that presents in template
|
3969
4048
|
*/
|
3970
4049
|
initCombos: function() {
|
3971
|
-
var
|
3972
|
-
|
3973
|
-
|
3974
|
-
|
3975
|
-
|
3976
|
-
|
3977
|
-
|
3978
|
-
that['$'+k].html(that.renderItems(items));
|
3979
|
-
}
|
3980
|
-
});
|
4050
|
+
for (var k in this.map) {
|
4051
|
+
var $c = this.$widget.find('.'+k);
|
4052
|
+
// set properties like this.$day, this.$month etc.
|
4053
|
+
this['$'+k] = $c.length ? $c : null;
|
4054
|
+
// fill with items
|
4055
|
+
this.fillCombo(k);
|
4056
|
+
}
|
3981
4057
|
},
|
3982
|
-
|
4058
|
+
|
4059
|
+
/*
|
4060
|
+
Fill combo with items
|
4061
|
+
*/
|
4062
|
+
fillCombo: function(k) {
|
4063
|
+
var $combo = this['$'+k];
|
4064
|
+
if (!$combo) {
|
4065
|
+
return;
|
4066
|
+
}
|
4067
|
+
|
4068
|
+
// define method name to fill items, e.g `fillDays`
|
4069
|
+
var f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1);
|
4070
|
+
var items = this[f]();
|
4071
|
+
var value = $combo.val();
|
4072
|
+
|
4073
|
+
$combo.empty();
|
4074
|
+
for(var i=0; i<items.length; i++) {
|
4075
|
+
$combo.append('<option value="'+items[i][0]+'">'+items[i][1]+'</option>');
|
4076
|
+
}
|
4077
|
+
|
4078
|
+
$combo.val(value);
|
4079
|
+
},
|
4080
|
+
|
3983
4081
|
/*
|
3984
4082
|
Initialize items of combos. Handles `firstItem` option
|
3985
4083
|
*/
|
3986
|
-
|
4084
|
+
fillCommon: function(key) {
|
3987
4085
|
var values = [],
|
3988
4086
|
relTime;
|
3989
4087
|
|
@@ -3998,27 +4096,29 @@ $(function(){
|
|
3998
4096
|
values.push(['', '']);
|
3999
4097
|
}
|
4000
4098
|
return values;
|
4001
|
-
},
|
4002
|
-
|
4003
|
-
/*
|
4004
|
-
render items to string of <option> tags
|
4005
|
-
*/
|
4006
|
-
renderItems: function(items) {
|
4007
|
-
var str = [];
|
4008
|
-
for(var i=0; i<items.length; i++) {
|
4009
|
-
str.push('<option value="'+items[i][0]+'">'+items[i][1]+'</option>');
|
4010
|
-
}
|
4011
|
-
return str.join("\n");
|
4012
|
-
},
|
4099
|
+
},
|
4100
|
+
|
4013
4101
|
|
4014
4102
|
/*
|
4015
4103
|
fill day
|
4016
4104
|
*/
|
4017
4105
|
fillDay: function() {
|
4018
|
-
var items = this.
|
4019
|
-
twoDigit = this.options.template.indexOf('DD') !== -1
|
4020
|
-
|
4021
|
-
|
4106
|
+
var items = this.fillCommon('d'), name, i,
|
4107
|
+
twoDigit = this.options.template.indexOf('DD') !== -1,
|
4108
|
+
daysCount = 31;
|
4109
|
+
|
4110
|
+
// detect days count (depends on month and year)
|
4111
|
+
// originally https://github.com/vitalets/combodate/pull/7
|
4112
|
+
if (this.options.smartDays && this.$month && this.$year) {
|
4113
|
+
var month = parseInt(this.$month.val(), 10);
|
4114
|
+
var year = parseInt(this.$year.val(), 10);
|
4115
|
+
|
4116
|
+
if (!isNaN(month) && !isNaN(year)) {
|
4117
|
+
daysCount = moment([year, month]).daysInMonth();
|
4118
|
+
}
|
4119
|
+
}
|
4120
|
+
|
4121
|
+
for (i = 1; i <= daysCount; i++) {
|
4022
4122
|
name = twoDigit ? this.leadZero(i) : i;
|
4023
4123
|
items.push([i, name]);
|
4024
4124
|
}
|
@@ -4029,7 +4129,7 @@ $(function(){
|
|
4029
4129
|
fill month
|
4030
4130
|
*/
|
4031
4131
|
fillMonth: function() {
|
4032
|
-
var items = this.
|
4132
|
+
var items = this.fillCommon('M'), name, i,
|
4033
4133
|
longNames = this.options.template.indexOf('MMMM') !== -1,
|
4034
4134
|
shortNames = this.options.template.indexOf('MMM') !== -1,
|
4035
4135
|
twoDigit = this.options.template.indexOf('MM') !== -1;
|
@@ -4062,7 +4162,7 @@ $(function(){
|
|
4062
4162
|
items[this.options.yearDescending ? 'push' : 'unshift']([i, name]);
|
4063
4163
|
}
|
4064
4164
|
|
4065
|
-
items = this.
|
4165
|
+
items = this.fillCommon('y').concat(items);
|
4066
4166
|
|
4067
4167
|
return items;
|
4068
4168
|
},
|
@@ -4071,7 +4171,7 @@ $(function(){
|
|
4071
4171
|
fill hour
|
4072
4172
|
*/
|
4073
4173
|
fillHour: function() {
|
4074
|
-
var items = this.
|
4174
|
+
var items = this.fillCommon('h'), name, i,
|
4075
4175
|
h12 = this.options.template.indexOf('h') !== -1,
|
4076
4176
|
h24 = this.options.template.indexOf('H') !== -1,
|
4077
4177
|
twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1,
|
@@ -4089,7 +4189,7 @@ $(function(){
|
|
4089
4189
|
fill minute
|
4090
4190
|
*/
|
4091
4191
|
fillMinute: function() {
|
4092
|
-
var items = this.
|
4192
|
+
var items = this.fillCommon('m'), name, i,
|
4093
4193
|
twoDigit = this.options.template.indexOf('mm') !== -1;
|
4094
4194
|
|
4095
4195
|
for(i=0; i<=59; i+= this.options.minuteStep) {
|
@@ -4103,7 +4203,7 @@ $(function(){
|
|
4103
4203
|
fill second
|
4104
4204
|
*/
|
4105
4205
|
fillSecond: function() {
|
4106
|
-
var items = this.
|
4206
|
+
var items = this.fillCommon('s'), name, i,
|
4107
4207
|
twoDigit = this.options.template.indexOf('ss') !== -1;
|
4108
4208
|
|
4109
4209
|
for(i=0; i<=59; i+= this.options.secondStep) {
|
@@ -4125,7 +4225,7 @@ $(function(){
|
|
4125
4225
|
];
|
4126
4226
|
return items;
|
4127
4227
|
},
|
4128
|
-
|
4228
|
+
|
4129
4229
|
/*
|
4130
4230
|
Returns current date value from combos.
|
4131
4231
|
If format not specified - `options.format` used.
|
@@ -4188,63 +4288,68 @@ $(function(){
|
|
4188
4288
|
that = this,
|
4189
4289
|
values = {};
|
4190
4290
|
|
4191
|
-
|
4192
|
-
|
4193
|
-
|
4194
|
-
|
4195
|
-
|
4196
|
-
|
4197
|
-
|
4198
|
-
|
4199
|
-
|
4200
|
-
|
4201
|
-
|
4202
|
-
|
4203
|
-
|
4204
|
-
|
4205
|
-
|
4291
|
+
//function to find nearest value in select options
|
4292
|
+
function getNearest($select, value) {
|
4293
|
+
var delta = {};
|
4294
|
+
$select.children('option').each(function(i, opt){
|
4295
|
+
var optValue = $(opt).attr('value'),
|
4296
|
+
distance;
|
4297
|
+
|
4298
|
+
if(optValue === '') return;
|
4299
|
+
distance = Math.abs(optValue - value);
|
4300
|
+
if(typeof delta.distance === 'undefined' || distance < delta.distance) {
|
4301
|
+
delta = {value: optValue, distance: distance};
|
4302
|
+
}
|
4303
|
+
});
|
4304
|
+
return delta.value;
|
4305
|
+
}
|
4206
4306
|
|
4207
4307
|
if(dt.isValid()) {
|
4208
|
-
|
4209
|
-
|
4210
|
-
|
4211
|
-
|
4212
|
-
|
4213
|
-
|
4214
|
-
|
4308
|
+
//read values from date object
|
4309
|
+
$.each(this.map, function(k, v) {
|
4310
|
+
if(k === 'ampm') {
|
4311
|
+
return;
|
4312
|
+
}
|
4313
|
+
values[k] = dt[v[1]]();
|
4314
|
+
});
|
4215
4315
|
|
4216
|
-
|
4217
|
-
|
4218
|
-
|
4219
|
-
|
4220
|
-
|
4221
|
-
|
4222
|
-
|
4223
|
-
|
4224
|
-
|
4225
|
-
|
4226
|
-
|
4227
|
-
|
4228
|
-
|
4229
|
-
|
4316
|
+
if(this.$ampm) {
|
4317
|
+
//12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day)
|
4318
|
+
if(values.hour >= 12) {
|
4319
|
+
values.ampm = 'pm';
|
4320
|
+
if(values.hour > 12) {
|
4321
|
+
values.hour -= 12;
|
4322
|
+
}
|
4323
|
+
} else {
|
4324
|
+
values.ampm = 'am';
|
4325
|
+
if(values.hour === 0) {
|
4326
|
+
values.hour = 12;
|
4327
|
+
}
|
4328
|
+
}
|
4329
|
+
}
|
4230
4330
|
|
4231
|
-
|
4232
|
-
|
4233
|
-
|
4331
|
+
$.each(values, function(k, v) {
|
4332
|
+
//call val() for each existing combo, e.g. this.$hour.val()
|
4333
|
+
if(that['$'+k]) {
|
4234
4334
|
|
4235
|
-
|
4236
|
-
|
4237
|
-
|
4335
|
+
if(k === 'minute' && that.options.minuteStep > 1 && that.options.roundTime) {
|
4336
|
+
v = getNearest(that['$'+k], v);
|
4337
|
+
}
|
4238
4338
|
|
4239
|
-
|
4240
|
-
|
4241
|
-
|
4339
|
+
if(k === 'second' && that.options.secondStep > 1 && that.options.roundTime) {
|
4340
|
+
v = getNearest(that['$'+k], v);
|
4341
|
+
}
|
4242
4342
|
|
4243
|
-
|
4244
|
-
|
4245
|
-
|
4343
|
+
that['$'+k].val(v);
|
4344
|
+
}
|
4345
|
+
});
|
4346
|
+
|
4347
|
+
// update days count
|
4348
|
+
if (this.options.smartDays) {
|
4349
|
+
this.fillCombo('day');
|
4350
|
+
}
|
4246
4351
|
|
4247
|
-
this.$element.val(dt.format(this.options.format));
|
4352
|
+
this.$element.val(dt.format(this.options.format)).change();
|
4248
4353
|
}
|
4249
4354
|
},
|
4250
4355
|
|
@@ -4319,10 +4424,11 @@ $(function(){
|
|
4319
4424
|
secondStep: 1,
|
4320
4425
|
firstItem: 'empty', //'name', 'empty', 'none'
|
4321
4426
|
errorClass: null,
|
4322
|
-
roundTime: true //whether to round minutes and seconds if step > 1
|
4427
|
+
roundTime: true, // whether to round minutes and seconds if step > 1
|
4428
|
+
smartDays: false // whether days in combo depend on selected month: 31, 30, 28
|
4323
4429
|
};
|
4324
4430
|
|
4325
|
-
}(window.jQuery));
|
4431
|
+
}(window.jQuery));
|
4326
4432
|
/**
|
4327
4433
|
Combodate input - dropdown date and time picker.
|
4328
4434
|
Based on [combodate](http://vitalets.github.com/combodate) plugin (included). To use it you should manually include [momentjs](http://momentjs.com).
|
@@ -4520,7 +4626,7 @@ $(function(){
|
|
4520
4626
|
$.fn.editabletypes.combodate = Constructor;
|
4521
4627
|
|
4522
4628
|
}(window.jQuery));
|
4523
|
-
|
4629
|
+
|
4524
4630
|
/*
|
4525
4631
|
Editableform based on Twitter Bootstrap 3
|
4526
4632
|
*/
|
@@ -4584,7 +4690,7 @@ Editableform based on Twitter Bootstrap 3
|
|
4584
4690
|
$.fn.editableform.errorBlockClass = null;
|
4585
4691
|
//engine
|
4586
4692
|
$.fn.editableform.engine = 'bs3';
|
4587
|
-
}(window.jQuery));
|
4693
|
+
}(window.jQuery));
|
4588
4694
|
/**
|
4589
4695
|
* Editable Popover3 (for Bootstrap 3)
|
4590
4696
|
* ---------------------
|
@@ -4767,16 +4873,43 @@ Editableform based on Twitter Bootstrap 3
|
|
4767
4873
|
var placement = typeof this.options.placement == 'function' ?
|
4768
4874
|
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
4769
4875
|
this.options.placement;
|
4876
|
+
|
4877
|
+
var autoToken = /\s?auto?\s?/i;
|
4878
|
+
var autoPlace = autoToken.test(placement);
|
4879
|
+
if (autoPlace) {
|
4880
|
+
placement = placement.replace(autoToken, '') || 'top';
|
4881
|
+
}
|
4770
4882
|
|
4771
4883
|
|
4772
4884
|
var pos = this.getPosition();
|
4773
4885
|
var actualWidth = $tip[0].offsetWidth;
|
4774
4886
|
var actualHeight = $tip[0].offsetHeight;
|
4887
|
+
|
4888
|
+
if (autoPlace) {
|
4889
|
+
var $parent = this.$element.parent();
|
4890
|
+
|
4891
|
+
var orgPlacement = placement;
|
4892
|
+
var docScroll = document.documentElement.scrollTop || document.body.scrollTop;
|
4893
|
+
var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth();
|
4894
|
+
var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight();
|
4895
|
+
var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left;
|
4896
|
+
|
4897
|
+
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
|
4898
|
+
placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
|
4899
|
+
placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
|
4900
|
+
placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
|
4901
|
+
placement;
|
4902
|
+
|
4903
|
+
$tip
|
4904
|
+
.removeClass(orgPlacement)
|
4905
|
+
.addClass(placement);
|
4906
|
+
}
|
4907
|
+
|
4908
|
+
|
4775
4909
|
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight);
|
4776
4910
|
|
4777
4911
|
this.applyPlacement(calculatedOffset, placement);
|
4778
|
-
|
4779
|
-
|
4912
|
+
|
4780
4913
|
|
4781
4914
|
}).call(this.container());
|
4782
4915
|
/*jshint laxcomma: false, eqeqeq: true*/
|
@@ -4784,7 +4917,7 @@ Editableform based on Twitter Bootstrap 3
|
|
4784
4917
|
});
|
4785
4918
|
|
4786
4919
|
}(window.jQuery));
|
4787
|
-
|
4920
|
+
|
4788
4921
|
/* =========================================================
|
4789
4922
|
* bootstrap-datepicker.js
|
4790
4923
|
* http://www.eyecon.ro/bootstrap-datepicker
|
@@ -6039,7 +6172,7 @@ Editableform based on Twitter Bootstrap 3
|
|
6039
6172
|
});
|
6040
6173
|
|
6041
6174
|
}( window.jQuery ));
|
6042
|
-
|
6175
|
+
|
6043
6176
|
/**
|
6044
6177
|
Bootstrap-datepicker.
|
6045
6178
|
Description and examples: https://github.com/eternicode/bootstrap-datepicker.
|
@@ -6238,7 +6371,7 @@ $(function(){
|
|
6238
6371
|
viewformat: null,
|
6239
6372
|
/**
|
6240
6373
|
Configuration of datepicker.
|
6241
|
-
Full list of options: http://
|
6374
|
+
Full list of options: http://bootstrap-datepicker.readthedocs.org/en/latest/options.html
|
6242
6375
|
|
6243
6376
|
@property datepicker
|
6244
6377
|
@type object
|
@@ -6269,7 +6402,7 @@ $(function(){
|
|
6269
6402
|
$.fn.editabletypes.date = Date;
|
6270
6403
|
|
6271
6404
|
}(window.jQuery));
|
6272
|
-
|
6405
|
+
|
6273
6406
|
/**
|
6274
6407
|
Bootstrap datefield input - modification for inline mode.
|
6275
6408
|
Shows normal <input type="text"> and binds popup datepicker.
|
@@ -6350,7 +6483,7 @@ Automatically shown in inline mode.
|
|
6350
6483
|
|
6351
6484
|
$.fn.editabletypes.datefield = DateField;
|
6352
6485
|
|
6353
|
-
}(window.jQuery));
|
6486
|
+
}(window.jQuery));
|
6354
6487
|
/**
|
6355
6488
|
Bootstrap-datetimepicker.
|
6356
6489
|
Based on [smalot bootstrap-datetimepicker plugin](https://github.com/smalot/bootstrap-datetimepicker).
|
@@ -6594,7 +6727,7 @@ $(function(){
|
|
6594
6727
|
|
6595
6728
|
$.fn.editabletypes.datetime = DateTime;
|
6596
6729
|
|
6597
|
-
}(window.jQuery));
|
6730
|
+
}(window.jQuery));
|
6598
6731
|
/**
|
6599
6732
|
Bootstrap datetimefield input - datetime input for inline mode.
|
6600
6733
|
Shows normal <input type="text"> and binds popup datetimepicker.
|