bootstrap-x-editable-rails 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
/*! X-editable - v1.
|
1
|
+
/*! X-editable - v1.4.0
|
2
2
|
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
3
3
|
* http://github.com/vitalets/x-editable
|
4
|
-
* Copyright (c)
|
4
|
+
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
5
5
|
|
6
6
|
/**
|
7
7
|
Form with single input element, two buttons and two states: normal/loading.
|
@@ -20,24 +20,16 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
20
20
|
if(!this.options.scope) {
|
21
21
|
this.options.scope = this;
|
22
22
|
}
|
23
|
-
|
23
|
+
//nothing shown after init
|
24
24
|
};
|
25
25
|
|
26
26
|
EditableForm.prototype = {
|
27
27
|
constructor: EditableForm,
|
28
28
|
initInput: function() { //called once
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
TypeConstructor = $.fn.editabletypes[this.options.type];
|
34
|
-
typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
|
35
|
-
this.input = new TypeConstructor(typeOptions);
|
36
|
-
} else {
|
37
|
-
$.error('Unknown type: '+ this.options.type);
|
38
|
-
return;
|
39
|
-
}
|
40
|
-
|
29
|
+
//take input from options (as it is created in editable-element)
|
30
|
+
this.input = this.options.input;
|
31
|
+
|
32
|
+
//set initial value
|
41
33
|
this.value = this.input.str2value(this.options.value);
|
42
34
|
},
|
43
35
|
initTemplate: function() {
|
@@ -52,47 +44,49 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
52
44
|
@method render
|
53
45
|
**/
|
54
46
|
render: function() {
|
47
|
+
//init loader
|
55
48
|
this.$loading = $($.fn.editableform.loading);
|
56
49
|
this.$div.empty().append(this.$loading);
|
57
|
-
this.showLoading();
|
58
50
|
|
59
51
|
//init form template and buttons
|
60
|
-
this.initTemplate();
|
52
|
+
this.initTemplate();
|
61
53
|
if(this.options.showbuttons) {
|
62
54
|
this.initButtons();
|
63
55
|
} else {
|
64
56
|
this.$form.find('.editable-buttons').remove();
|
65
57
|
}
|
66
58
|
|
59
|
+
//show loading state
|
60
|
+
this.showLoading();
|
61
|
+
|
67
62
|
/**
|
68
63
|
Fired when rendering starts
|
69
64
|
@event rendering
|
70
65
|
@param {Object} event event object
|
71
66
|
**/
|
72
67
|
this.$div.triggerHandler('rendering');
|
68
|
+
|
69
|
+
//init input
|
70
|
+
this.initInput();
|
71
|
+
|
72
|
+
//append input to form
|
73
|
+
this.input.prerender();
|
74
|
+
this.$form.find('div.editable-input').append(this.input.$tpl);
|
73
75
|
|
76
|
+
//append form to container
|
77
|
+
this.$div.append(this.$form);
|
78
|
+
|
74
79
|
//render input
|
75
80
|
$.when(this.input.render())
|
76
81
|
.then($.proxy(function () {
|
77
|
-
//input
|
78
|
-
this.$form.find('div.editable-input').append(this.input.$input);
|
79
|
-
|
80
|
-
//automatically submit inputs when no buttons shown
|
82
|
+
//setup input to submit automatically when no buttons shown
|
81
83
|
if(!this.options.showbuttons) {
|
82
84
|
this.input.autosubmit();
|
83
85
|
}
|
84
|
-
|
85
|
-
//"clear" link
|
86
|
-
if(this.input.$clear) {
|
87
|
-
this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear));
|
88
|
-
}
|
89
|
-
|
90
|
-
//append form to container
|
91
|
-
this.$div.append(this.$form);
|
92
86
|
|
93
87
|
//attach 'cancel' handler
|
94
88
|
this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
|
95
|
-
|
89
|
+
|
96
90
|
if(this.input.error) {
|
97
91
|
this.error(this.input.error);
|
98
92
|
this.$form.find('.editable-submit').attr('disabled', true);
|
@@ -116,6 +110,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
116
110
|
this.$div.triggerHandler('rendered');
|
117
111
|
|
118
112
|
this.showForm();
|
113
|
+
|
114
|
+
//call postrender method to perform actions required visibility of form
|
115
|
+
if(this.input.postrender) {
|
116
|
+
this.input.postrender();
|
117
|
+
}
|
119
118
|
}, this));
|
120
119
|
},
|
121
120
|
cancel: function() {
|
@@ -127,11 +126,17 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
127
126
|
this.$div.triggerHandler('cancel');
|
128
127
|
},
|
129
128
|
showLoading: function() {
|
130
|
-
var w;
|
129
|
+
var w, h;
|
131
130
|
if(this.$form) {
|
132
|
-
//set loading size equal to form
|
133
|
-
this.$
|
134
|
-
this.$
|
131
|
+
//set loading size equal to form
|
132
|
+
w = this.$form.outerWidth();
|
133
|
+
h = this.$form.outerHeight();
|
134
|
+
if(w) {
|
135
|
+
this.$loading.width(w);
|
136
|
+
}
|
137
|
+
if(h) {
|
138
|
+
this.$loading.height(h);
|
139
|
+
}
|
135
140
|
this.$form.hide();
|
136
141
|
} else {
|
137
142
|
//stretch loading to fill container width
|
@@ -159,14 +164,23 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
159
164
|
|
160
165
|
error: function(msg) {
|
161
166
|
var $group = this.$form.find('.control-group'),
|
162
|
-
|
167
|
+
$block = this.$form.find('.editable-error-block'),
|
168
|
+
lines;
|
163
169
|
|
164
170
|
if(msg === false) {
|
165
171
|
$group.removeClass($.fn.editableform.errorGroupClass);
|
166
172
|
$block.removeClass($.fn.editableform.errorBlockClass).empty().hide();
|
167
173
|
} else {
|
174
|
+
//convert newline to <br> for more pretty error display
|
175
|
+
if(msg) {
|
176
|
+
lines = msg.split("\n");
|
177
|
+
for (var i = 0; i < lines.length; i++) {
|
178
|
+
lines[i] = $('<div>').text(lines[i]).html();
|
179
|
+
}
|
180
|
+
msg = lines.join('<br>');
|
181
|
+
}
|
168
182
|
$group.addClass($.fn.editableform.errorGroupClass);
|
169
|
-
$block.addClass($.fn.editableform.errorBlockClass).
|
183
|
+
$block.addClass($.fn.editableform.errorBlockClass).html(msg).show();
|
170
184
|
}
|
171
185
|
},
|
172
186
|
|
@@ -299,10 +313,15 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
299
313
|
},
|
300
314
|
|
301
315
|
option: function(key, value) {
|
302
|
-
this.options
|
316
|
+
if(key in this.options) {
|
317
|
+
this.options[key] = value;
|
318
|
+
}
|
319
|
+
|
303
320
|
if(key === 'value') {
|
304
321
|
this.setValue(value);
|
305
322
|
}
|
323
|
+
|
324
|
+
//do not pass option to input as it is passed in editable-element
|
306
325
|
},
|
307
326
|
|
308
327
|
setValue: function(value, convertStr) {
|
@@ -311,6 +330,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
311
330
|
} else {
|
312
331
|
this.value = value;
|
313
332
|
}
|
333
|
+
|
334
|
+
//if form is visible, update input
|
335
|
+
if(this.$form && this.$form.is(':visible')) {
|
336
|
+
this.input.value2input(this.value);
|
337
|
+
}
|
314
338
|
}
|
315
339
|
};
|
316
340
|
|
@@ -372,7 +396,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
372
396
|
url: function(params) {
|
373
397
|
if(params.value === 'abc') {
|
374
398
|
var d = new $.Deferred;
|
375
|
-
return d.reject('
|
399
|
+
return d.reject('error message'); //returning error via deferred object
|
376
400
|
} else {
|
377
401
|
someModel.set(params.name, params.value); //save data in some js model
|
378
402
|
}
|
@@ -463,21 +487,21 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
463
487
|
/**
|
464
488
|
Additional options for ajax request.
|
465
489
|
List of values: http://api.jquery.com/jQuery.ajax
|
466
|
-
|
490
|
+
|
467
491
|
@property ajaxOptions
|
468
492
|
@type object
|
469
493
|
@default null
|
470
494
|
@since 1.1.1
|
495
|
+
@example
|
496
|
+
ajaxOptions: {
|
497
|
+
type: 'put',
|
498
|
+
dataType: 'json'
|
499
|
+
}
|
471
500
|
**/
|
472
501
|
ajaxOptions: null,
|
473
502
|
/**
|
474
503
|
Whether to show buttons or not.
|
475
|
-
Form without buttons
|
476
|
-
@example
|
477
|
-
ajaxOptions: {
|
478
|
-
method: 'PUT',
|
479
|
-
dataType: 'xml'
|
480
|
-
}
|
504
|
+
Form without buttons is auto-submitted.
|
481
505
|
|
482
506
|
@property showbuttons
|
483
507
|
@type boolean
|
@@ -621,19 +645,22 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
621
645
|
return newObj;
|
622
646
|
},
|
623
647
|
|
624
|
-
|
625
|
-
|
648
|
+
/*
|
649
|
+
exclude complex objects from $.data() before pass to config
|
626
650
|
*/
|
627
651
|
getConfigData: function($element) {
|
628
652
|
var data = {};
|
629
653
|
$.each($element.data(), function(k, v) {
|
630
|
-
if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) {
|
654
|
+
if(typeof v !== 'object' || (v && typeof v === 'object' && (v.constructor === Object || v.constructor === Array))) {
|
631
655
|
data[k] = v;
|
632
656
|
}
|
633
657
|
});
|
634
658
|
return data;
|
635
659
|
},
|
636
660
|
|
661
|
+
/*
|
662
|
+
returns keys of object
|
663
|
+
*/
|
637
664
|
objectKeys: function(o) {
|
638
665
|
if (Object.keys) {
|
639
666
|
return Object.keys(o);
|
@@ -657,9 +684,82 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
657
684
|
**/
|
658
685
|
escape: function(str) {
|
659
686
|
return $('<div>').text(str).html();
|
660
|
-
}
|
687
|
+
},
|
688
|
+
|
689
|
+
/*
|
690
|
+
returns array items from sourceData having value property equal or inArray of 'value'
|
691
|
+
*/
|
692
|
+
itemsByValue: function(value, sourceData) {
|
693
|
+
if(!sourceData || value === null) {
|
694
|
+
return [];
|
695
|
+
}
|
696
|
+
|
697
|
+
//convert to array
|
698
|
+
if(!$.isArray(value)) {
|
699
|
+
value = [value];
|
700
|
+
}
|
701
|
+
|
702
|
+
/*jslint eqeq: true*/
|
703
|
+
var result = $.grep(sourceData, function(o){
|
704
|
+
return $.grep(value, function(v){ return v == o.value; }).length;
|
705
|
+
});
|
706
|
+
/*jslint eqeq: false*/
|
707
|
+
|
708
|
+
return result;
|
709
|
+
},
|
710
|
+
|
711
|
+
/*
|
712
|
+
Returns input by options: type, mode.
|
713
|
+
*/
|
714
|
+
createInput: function(options) {
|
715
|
+
var TypeConstructor, typeOptions, input,
|
716
|
+
type = options.type;
|
717
|
+
|
718
|
+
//`date` is some kind of virtual type that is transformed to one of exact types
|
719
|
+
//depending on mode and core lib
|
720
|
+
if(type === 'date') {
|
721
|
+
//inline
|
722
|
+
if(options.mode === 'inline') {
|
723
|
+
if($.fn.editabletypes.datefield) {
|
724
|
+
type = 'datefield';
|
725
|
+
} else if($.fn.editabletypes.dateuifield) {
|
726
|
+
type = 'dateuifield';
|
727
|
+
}
|
728
|
+
//popup
|
729
|
+
} else {
|
730
|
+
if($.fn.editabletypes.date) {
|
731
|
+
type = 'date';
|
732
|
+
} else if($.fn.editabletypes.dateui) {
|
733
|
+
type = 'dateui';
|
734
|
+
}
|
735
|
+
}
|
736
|
+
|
737
|
+
//if type still `date` and not exist in types, replace with `combodate` that is base input
|
738
|
+
if(type === 'date' && !$.fn.editabletypes.date) {
|
739
|
+
type = 'combodate';
|
740
|
+
}
|
741
|
+
}
|
742
|
+
|
743
|
+
//change wysihtml5 to textarea for jquery UI and plain versions
|
744
|
+
if(type === 'wysihtml5' && !$.fn.editabletypes[type]) {
|
745
|
+
type = 'textarea';
|
746
|
+
}
|
747
|
+
|
748
|
+
//create input of specified type. Input will be used for converting value, not in form
|
749
|
+
if(typeof $.fn.editabletypes[type] === 'function') {
|
750
|
+
TypeConstructor = $.fn.editabletypes[type];
|
751
|
+
typeOptions = this.sliceObj(options, this.objectKeys(TypeConstructor.defaults));
|
752
|
+
input = new TypeConstructor(typeOptions);
|
753
|
+
return input;
|
754
|
+
} else {
|
755
|
+
$.error('Unknown type: '+ type);
|
756
|
+
return false;
|
757
|
+
}
|
758
|
+
}
|
759
|
+
|
661
760
|
};
|
662
761
|
}(window.jQuery));
|
762
|
+
|
663
763
|
/**
|
664
764
|
Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br>
|
665
765
|
This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br>
|
@@ -671,12 +771,16 @@ Applied as jQuery method.
|
|
671
771
|
**/
|
672
772
|
(function ($) {
|
673
773
|
|
674
|
-
var
|
774
|
+
var Popup = function (element, options) {
|
675
775
|
this.init(element, options);
|
676
776
|
};
|
777
|
+
|
778
|
+
var Inline = function (element, options) {
|
779
|
+
this.init(element, options);
|
780
|
+
};
|
677
781
|
|
678
782
|
//methods
|
679
|
-
|
783
|
+
Popup.prototype = {
|
680
784
|
containerName: null, //tbd in child class
|
681
785
|
innerCss: null, //tbd in child class
|
682
786
|
init: function(element, options) {
|
@@ -684,6 +788,10 @@ Applied as jQuery method.
|
|
684
788
|
//todo: what is in priority: data or js?
|
685
789
|
this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options);
|
686
790
|
this.splitOptions();
|
791
|
+
|
792
|
+
//set scope of form callbacks to element
|
793
|
+
this.formOptions.scope = this.$element[0];
|
794
|
+
|
687
795
|
this.initContainer();
|
688
796
|
|
689
797
|
//bind 'destroyed' listener to destroy container when element is removed from dom
|
@@ -691,7 +799,7 @@ Applied as jQuery method.
|
|
691
799
|
this.destroy();
|
692
800
|
}, this));
|
693
801
|
|
694
|
-
//attach document
|
802
|
+
//attach document handler to close containers on click / escape
|
695
803
|
if(!$(document).data('editable-handlers-attached')) {
|
696
804
|
//close all on escape
|
697
805
|
$(document).on('keyup.editable', function (e) {
|
@@ -703,15 +811,22 @@ Applied as jQuery method.
|
|
703
811
|
|
704
812
|
//close containers when click outside
|
705
813
|
$(document).on('click.editable', function(e) {
|
706
|
-
var $target = $(e.target)
|
814
|
+
var $target = $(e.target), i,
|
815
|
+
exclude_classes = ['.editable-container',
|
816
|
+
'.ui-datepicker-header',
|
817
|
+
'.modal-backdrop',
|
818
|
+
'.bootstrap-wysihtml5-insert-image-modal',
|
819
|
+
'.bootstrap-wysihtml5-insert-link-modal'];
|
707
820
|
|
708
|
-
//if click inside
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
EditableContainer.prototype.closeOthers(e.target);
|
821
|
+
//if click inside one of exclude classes --> no nothing
|
822
|
+
for(i=0; i<exclude_classes.length; i++) {
|
823
|
+
if($target.is(exclude_classes[i]) || $target.parents(exclude_classes[i]).length) {
|
824
|
+
return;
|
825
|
+
}
|
714
826
|
}
|
827
|
+
|
828
|
+
//close all open containers (except one - target)
|
829
|
+
Popup.prototype.closeOthers(e.target);
|
715
830
|
});
|
716
831
|
|
717
832
|
$(document).data('editable-handlers-attached', true);
|
@@ -723,6 +838,7 @@ Applied as jQuery method.
|
|
723
838
|
this.containerOptions = {};
|
724
839
|
this.formOptions = {};
|
725
840
|
var cDef = $.fn[this.containerName].defaults;
|
841
|
+
//keys defined in container defaults go to container, others go to form
|
726
842
|
for(var k in this.options) {
|
727
843
|
if(k in cDef) {
|
728
844
|
this.containerOptions[k] = this.options[k];
|
@@ -732,18 +848,34 @@ Applied as jQuery method.
|
|
732
848
|
}
|
733
849
|
},
|
734
850
|
|
851
|
+
/*
|
852
|
+
Returns jquery object of container
|
853
|
+
@method tip()
|
854
|
+
*/
|
855
|
+
tip: function() {
|
856
|
+
return this.container() ? this.container().$tip : null;
|
857
|
+
},
|
858
|
+
|
859
|
+
/* returns container object */
|
860
|
+
container: function() {
|
861
|
+
return this.$element.data(this.containerName);
|
862
|
+
},
|
863
|
+
|
864
|
+
call: function() {
|
865
|
+
this.$element[this.containerName].apply(this.$element, arguments);
|
866
|
+
},
|
867
|
+
|
735
868
|
initContainer: function(){
|
736
869
|
this.call(this.containerOptions);
|
737
870
|
},
|
738
871
|
|
739
|
-
|
740
|
-
this
|
741
|
-
this.$form = $('<div>')
|
872
|
+
renderForm: function() {
|
873
|
+
this.$form
|
742
874
|
.editableform(this.formOptions)
|
743
875
|
.on({
|
744
|
-
save: $.proxy(this.save, this),
|
745
|
-
|
746
|
-
|
876
|
+
save: $.proxy(this.save, this), //click on submit button (value changed)
|
877
|
+
nochange: $.proxy(function(){ this.hide('nochange'); }, this), //click on submit button (value NOT changed)
|
878
|
+
cancel: $.proxy(function(){ this.hide('cancel'); }, this), //click on calcel button
|
747
879
|
show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state)
|
748
880
|
rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown
|
749
881
|
rendered: $.proxy(function(){
|
@@ -760,31 +892,16 @@ Applied as jQuery method.
|
|
760
892
|
**/
|
761
893
|
this.$element.triggerHandler('shown');
|
762
894
|
}, this)
|
763
|
-
})
|
764
|
-
|
895
|
+
})
|
896
|
+
.editableform('render');
|
765
897
|
},
|
766
898
|
|
767
|
-
/*
|
768
|
-
Returns jquery object of container
|
769
|
-
@method tip()
|
770
|
-
*/
|
771
|
-
tip: function() {
|
772
|
-
return this.container().$tip;
|
773
|
-
},
|
774
|
-
|
775
|
-
container: function() {
|
776
|
-
return this.$element.data(this.containerName);
|
777
|
-
},
|
778
|
-
|
779
|
-
call: function() {
|
780
|
-
this.$element[this.containerName].apply(this.$element, arguments);
|
781
|
-
},
|
782
|
-
|
783
899
|
/**
|
784
900
|
Shows container with form
|
785
901
|
@method show()
|
786
902
|
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
787
|
-
**/
|
903
|
+
**/
|
904
|
+
/* Note: poshytip owerwrites this method totally! */
|
788
905
|
show: function (closeAll) {
|
789
906
|
this.$element.addClass('editable-open');
|
790
907
|
if(closeAll !== false) {
|
@@ -792,16 +909,37 @@ Applied as jQuery method.
|
|
792
909
|
this.closeOthers(this.$element[0]);
|
793
910
|
}
|
794
911
|
|
912
|
+
//show container itself
|
795
913
|
this.innerShow();
|
796
|
-
},
|
797
|
-
|
798
|
-
/* internal show method. To be overwritten in child classes */
|
799
|
-
innerShow: function () {
|
800
|
-
this.call('show');
|
801
914
|
this.tip().addClass('editable-container');
|
802
|
-
|
803
|
-
|
804
|
-
|
915
|
+
|
916
|
+
/*
|
917
|
+
Currently, form is re-rendered on every show.
|
918
|
+
The main reason is that we dont know, what container will do with content when closed:
|
919
|
+
remove(), detach() or just hide().
|
920
|
+
|
921
|
+
Detaching form itself before hide and re-insert before show is good solution,
|
922
|
+
but visually it looks ugly, as container changes size before hide.
|
923
|
+
*/
|
924
|
+
|
925
|
+
//if form already exist - delete previous data
|
926
|
+
if(this.$form) {
|
927
|
+
//todo: destroy prev data!
|
928
|
+
//this.$form.destroy();
|
929
|
+
}
|
930
|
+
|
931
|
+
this.$form = $('<div>');
|
932
|
+
|
933
|
+
//insert form into container body
|
934
|
+
if(this.tip().is(this.innerCss)) {
|
935
|
+
//for inline container
|
936
|
+
this.tip().append(this.$form);
|
937
|
+
} else {
|
938
|
+
this.tip().find(this.innerCss).append(this.$form);
|
939
|
+
}
|
940
|
+
|
941
|
+
//render form
|
942
|
+
this.renderForm();
|
805
943
|
},
|
806
944
|
|
807
945
|
/**
|
@@ -813,8 +951,10 @@ Applied as jQuery method.
|
|
813
951
|
if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) {
|
814
952
|
return;
|
815
953
|
}
|
954
|
+
|
816
955
|
this.$element.removeClass('editable-open');
|
817
956
|
this.innerHide();
|
957
|
+
|
818
958
|
/**
|
819
959
|
Fired when container was hidden. It occurs on both save or cancel.
|
820
960
|
|
@@ -832,9 +972,14 @@ Applied as jQuery method.
|
|
832
972
|
this.$element.triggerHandler('hidden', reason);
|
833
973
|
},
|
834
974
|
|
975
|
+
/* internal show method. To be overwritten in child classes */
|
976
|
+
innerShow: function () {
|
977
|
+
|
978
|
+
},
|
979
|
+
|
835
980
|
/* internal hide method. To be overwritten in child classes */
|
836
981
|
innerHide: function () {
|
837
|
-
|
982
|
+
|
838
983
|
},
|
839
984
|
|
840
985
|
/**
|
@@ -843,7 +988,7 @@ Applied as jQuery method.
|
|
843
988
|
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
844
989
|
**/
|
845
990
|
toggle: function(closeAll) {
|
846
|
-
if(this.tip && this.tip().is(':visible')) {
|
991
|
+
if(this.container() && this.tip() && this.tip().is(':visible')) {
|
847
992
|
this.hide();
|
848
993
|
} else {
|
849
994
|
this.show(closeAll);
|
@@ -911,9 +1056,17 @@ Applied as jQuery method.
|
|
911
1056
|
@method destroy()
|
912
1057
|
**/
|
913
1058
|
destroy: function() {
|
914
|
-
this.
|
1059
|
+
this.hide();
|
1060
|
+
this.innerDestroy();
|
1061
|
+
this.$element.off('destroyed');
|
1062
|
+
this.$element.removeData('editableContainer');
|
915
1063
|
},
|
916
1064
|
|
1065
|
+
/* to be overwritten in child classes */
|
1066
|
+
innerDestroy: function() {
|
1067
|
+
|
1068
|
+
},
|
1069
|
+
|
917
1070
|
/*
|
918
1071
|
Closes other containers except one related to passed element.
|
919
1072
|
Other containers can be cancelled or submitted (depends on onblur option)
|
@@ -972,11 +1125,12 @@ Applied as jQuery method.
|
|
972
1125
|
return this.each(function () {
|
973
1126
|
var $this = $(this),
|
974
1127
|
dataKey = 'editableContainer',
|
975
|
-
data = $this.data(dataKey),
|
976
|
-
options = typeof option === 'object' && option
|
1128
|
+
data = $this.data(dataKey),
|
1129
|
+
options = typeof option === 'object' && option,
|
1130
|
+
Constructor = (options.mode === 'inline') ? Inline : Popup;
|
977
1131
|
|
978
1132
|
if (!data) {
|
979
|
-
$this.data(dataKey, (data = new
|
1133
|
+
$this.data(dataKey, (data = new Constructor(this, options)));
|
980
1134
|
}
|
981
1135
|
|
982
1136
|
if (typeof option === 'string') { //call method
|
@@ -985,8 +1139,9 @@ Applied as jQuery method.
|
|
985
1139
|
});
|
986
1140
|
};
|
987
1141
|
|
988
|
-
//store
|
989
|
-
$.fn.editableContainer.
|
1142
|
+
//store constructors
|
1143
|
+
$.fn.editableContainer.Popup = Popup;
|
1144
|
+
$.fn.editableContainer.Inline = Inline;
|
990
1145
|
|
991
1146
|
//defaults
|
992
1147
|
$.fn.editableContainer.defaults = {
|
@@ -1025,7 +1180,25 @@ Applied as jQuery method.
|
|
1025
1180
|
@default 'cancel'
|
1026
1181
|
@since 1.1.1
|
1027
1182
|
**/
|
1028
|
-
onblur: 'cancel'
|
1183
|
+
onblur: 'cancel',
|
1184
|
+
|
1185
|
+
/**
|
1186
|
+
Animation speed (inline mode)
|
1187
|
+
@property anim
|
1188
|
+
@type string
|
1189
|
+
@default 'fast'
|
1190
|
+
**/
|
1191
|
+
anim: 'fast',
|
1192
|
+
|
1193
|
+
/**
|
1194
|
+
Mode of editable, can be `popup` or `inline`
|
1195
|
+
|
1196
|
+
@property mode
|
1197
|
+
@type string
|
1198
|
+
@default 'popup'
|
1199
|
+
@since 1.4.0
|
1200
|
+
**/
|
1201
|
+
mode: 'popup'
|
1029
1202
|
};
|
1030
1203
|
|
1031
1204
|
/*
|
@@ -1042,6 +1215,56 @@ Applied as jQuery method.
|
|
1042
1215
|
|
1043
1216
|
}(window.jQuery));
|
1044
1217
|
|
1218
|
+
/**
|
1219
|
+
* Editable Inline
|
1220
|
+
* ---------------------
|
1221
|
+
*/
|
1222
|
+
(function ($) {
|
1223
|
+
|
1224
|
+
//copy prototype from EditableContainer
|
1225
|
+
//extend methods
|
1226
|
+
$.extend($.fn.editableContainer.Inline.prototype, $.fn.editableContainer.Popup.prototype, {
|
1227
|
+
containerName: 'editableform',
|
1228
|
+
innerCss: '.editable-inline',
|
1229
|
+
|
1230
|
+
initContainer: function(){
|
1231
|
+
//container is <span> element
|
1232
|
+
this.$tip = $('<span></span>').addClass('editable-inline');
|
1233
|
+
|
1234
|
+
//convert anim to miliseconds (int)
|
1235
|
+
if(!this.options.anim) {
|
1236
|
+
this.options.anim = 0;
|
1237
|
+
}
|
1238
|
+
},
|
1239
|
+
|
1240
|
+
splitOptions: function() {
|
1241
|
+
//all options are passed to form
|
1242
|
+
this.containerOptions = {};
|
1243
|
+
this.formOptions = this.options;
|
1244
|
+
},
|
1245
|
+
|
1246
|
+
tip: function() {
|
1247
|
+
return this.$tip;
|
1248
|
+
},
|
1249
|
+
|
1250
|
+
innerShow: function () {
|
1251
|
+
this.$element.hide();
|
1252
|
+
this.tip().insertAfter(this.$element).show();
|
1253
|
+
},
|
1254
|
+
|
1255
|
+
innerHide: function () {
|
1256
|
+
this.$tip.hide(this.options.anim, $.proxy(function() {
|
1257
|
+
this.$element.show();
|
1258
|
+
this.tip().empty().remove();
|
1259
|
+
}, this));
|
1260
|
+
},
|
1261
|
+
|
1262
|
+
innerDestroy: function() {
|
1263
|
+
this.tip().remove();
|
1264
|
+
}
|
1265
|
+
});
|
1266
|
+
|
1267
|
+
}(window.jQuery));
|
1045
1268
|
/**
|
1046
1269
|
Makes editable any HTML element on the page. Applied as jQuery method.
|
1047
1270
|
|
@@ -1059,27 +1282,15 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1059
1282
|
Editable.prototype = {
|
1060
1283
|
constructor: Editable,
|
1061
1284
|
init: function () {
|
1062
|
-
var
|
1063
|
-
|
1064
|
-
|
1065
|
-
finalize;
|
1066
|
-
|
1067
|
-
//editableContainer must be defined
|
1068
|
-
if(!$.fn.editableContainer) {
|
1069
|
-
$.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)');
|
1070
|
-
return;
|
1071
|
-
}
|
1072
|
-
|
1285
|
+
var isValueByText = false,
|
1286
|
+
doAutotext, finalize;
|
1287
|
+
|
1073
1288
|
//name
|
1074
1289
|
this.options.name = this.options.name || this.$element.attr('id');
|
1075
1290
|
|
1076
1291
|
//create input of specified type. Input will be used for converting value, not in form
|
1077
|
-
|
1078
|
-
|
1079
|
-
this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
|
1080
|
-
this.input = new TypeConstructor(this.typeOptions);
|
1081
|
-
} else {
|
1082
|
-
$.error('Unknown type: '+ this.options.type);
|
1292
|
+
this.input = $.fn.editableutils.createInput(this.options);
|
1293
|
+
if(!this.input) {
|
1083
1294
|
return;
|
1084
1295
|
}
|
1085
1296
|
|
@@ -1140,8 +1351,12 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1140
1351
|
|
1141
1352
|
@event init
|
1142
1353
|
@param {Object} event event object
|
1143
|
-
@param {Object} editable editable instance
|
1354
|
+
@param {Object} editable editable instance (as here it cannot accessed via data('editable'))
|
1144
1355
|
@since 1.2.0
|
1356
|
+
@example
|
1357
|
+
$('#username').on('init', function(e, editable) {
|
1358
|
+
alert('initialized ' + editable.options.name);
|
1359
|
+
});
|
1145
1360
|
**/
|
1146
1361
|
this.$element.triggerHandler('init', this);
|
1147
1362
|
}, this));
|
@@ -1152,18 +1367,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1152
1367
|
Can call custom display method from options.
|
1153
1368
|
Can return deferred object.
|
1154
1369
|
@method render()
|
1370
|
+
@param {mixed} response server response (if exist) to pass into display function
|
1155
1371
|
*/
|
1156
|
-
render: function() {
|
1372
|
+
render: function(response) {
|
1157
1373
|
//do not display anything
|
1158
1374
|
if(this.options.display === false) {
|
1159
1375
|
return;
|
1160
1376
|
}
|
1377
|
+
|
1161
1378
|
//if it is input with source, we pass callback in third param to be called when source is loaded
|
1162
1379
|
if(this.input.options.hasOwnProperty('source')) {
|
1163
|
-
return this.input.value2html(this.value, this.$element[0], this.options.display);
|
1380
|
+
return this.input.value2html(this.value, this.$element[0], this.options.display, response);
|
1164
1381
|
//if display method defined --> use it
|
1165
1382
|
} else if(typeof this.options.display === 'function') {
|
1166
|
-
return this.options.display.call(this.$element[0], this.value);
|
1383
|
+
return this.options.display.call(this.$element[0], this.value, response);
|
1167
1384
|
//else use input's original value2html() method
|
1168
1385
|
} else {
|
1169
1386
|
return this.input.value2html(this.value, this.$element[0]);
|
@@ -1233,12 +1450,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1233
1450
|
|
1234
1451
|
//disabled
|
1235
1452
|
if(key === 'disabled') {
|
1236
|
-
|
1237
|
-
this.disable();
|
1238
|
-
} else {
|
1239
|
-
this.enable();
|
1240
|
-
}
|
1241
|
-
return;
|
1453
|
+
return value ? this.disable() : this.enable();
|
1242
1454
|
}
|
1243
1455
|
|
1244
1456
|
//value
|
@@ -1250,6 +1462,12 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1250
1462
|
if(this.container) {
|
1251
1463
|
this.container.option(key, value);
|
1252
1464
|
}
|
1465
|
+
|
1466
|
+
//pass option to input directly (as it points to the same in form)
|
1467
|
+
if(this.input.option) {
|
1468
|
+
this.input.option(key, value);
|
1469
|
+
}
|
1470
|
+
|
1253
1471
|
},
|
1254
1472
|
|
1255
1473
|
/*
|
@@ -1291,7 +1509,8 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1291
1509
|
//init editableContainer: popover, tooltip, inline, etc..
|
1292
1510
|
if(!this.container) {
|
1293
1511
|
var containerOptions = $.extend({}, this.options, {
|
1294
|
-
value: this.value
|
1512
|
+
value: this.value,
|
1513
|
+
input: this.input //pass input to form (as it is already created)
|
1295
1514
|
});
|
1296
1515
|
this.$element.editableContainer(containerOptions);
|
1297
1516
|
this.$element.on("save.internal", $.proxy(this.save, this));
|
@@ -1338,8 +1557,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1338
1557
|
this.$element.removeClass('editable-unsaved');
|
1339
1558
|
}
|
1340
1559
|
|
1341
|
-
|
1342
|
-
this.setValue(params.newValue);
|
1560
|
+
this.setValue(params.newValue, false, params.response);
|
1343
1561
|
|
1344
1562
|
/**
|
1345
1563
|
Fired when new value was submitted. You can use <code>$(this).data('editable')</code> to access to editable instance
|
@@ -1351,13 +1569,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1351
1569
|
@param {Object} params.response ajax response
|
1352
1570
|
@example
|
1353
1571
|
$('#username').on('save', function(e, params) {
|
1354
|
-
|
1355
|
-
var pk = $(this).data('editable').options.pk;
|
1356
|
-
if(params.response && params.response.success) {
|
1357
|
-
alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
|
1358
|
-
} else {
|
1359
|
-
alert('error!');
|
1360
|
-
}
|
1572
|
+
alert('Saved value: ' + params.newValue);
|
1361
1573
|
});
|
1362
1574
|
**/
|
1363
1575
|
//event itself is triggered by editableContainer. Description here is only for documentation
|
@@ -1375,7 +1587,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1375
1587
|
@param {mixed} value new value
|
1376
1588
|
@param {boolean} convertStr whether to convert value from string to internal format
|
1377
1589
|
**/
|
1378
|
-
setValue: function(value, convertStr) {
|
1590
|
+
setValue: function(value, convertStr, response) {
|
1379
1591
|
if(convertStr) {
|
1380
1592
|
this.value = this.input.str2value(value);
|
1381
1593
|
} else {
|
@@ -1384,7 +1596,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1384
1596
|
if(this.container) {
|
1385
1597
|
this.container.option('value', this.value);
|
1386
1598
|
}
|
1387
|
-
$.when(this.render())
|
1599
|
+
$.when(this.render(response))
|
1388
1600
|
.then($.proxy(function() {
|
1389
1601
|
this.handleEmpty();
|
1390
1602
|
}, this));
|
@@ -1398,7 +1610,28 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1398
1610
|
if(this.container) {
|
1399
1611
|
this.container.activate();
|
1400
1612
|
}
|
1401
|
-
}
|
1613
|
+
},
|
1614
|
+
|
1615
|
+
/**
|
1616
|
+
Removes editable feature from element
|
1617
|
+
@method destroy()
|
1618
|
+
**/
|
1619
|
+
destroy: function() {
|
1620
|
+
if(this.container) {
|
1621
|
+
this.container.destroy();
|
1622
|
+
}
|
1623
|
+
|
1624
|
+
if(this.options.toggle !== 'manual') {
|
1625
|
+
this.$element.removeClass('editable-click');
|
1626
|
+
this.$element.off(this.options.toggle + '.editable');
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
this.$element.off("save.internal");
|
1630
|
+
|
1631
|
+
this.$element.removeClass('editable');
|
1632
|
+
this.$element.removeClass('editable-open');
|
1633
|
+
this.$element.removeData('editable');
|
1634
|
+
}
|
1402
1635
|
};
|
1403
1636
|
|
1404
1637
|
/* EDITABLE PLUGIN DEFINITION
|
@@ -1584,7 +1817,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1584
1817
|
**/
|
1585
1818
|
autotext: 'auto',
|
1586
1819
|
/**
|
1587
|
-
Initial value of input.
|
1820
|
+
Initial value of input. If not set, taken from element's text.
|
1588
1821
|
|
1589
1822
|
@property value
|
1590
1823
|
@type mixed
|
@@ -1593,10 +1826,21 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1593
1826
|
value: null,
|
1594
1827
|
/**
|
1595
1828
|
Callback to perform custom displaying of value in element's text.
|
1596
|
-
If
|
1597
|
-
If
|
1829
|
+
If `null`, default input's display used.
|
1830
|
+
If `false`, no displaying methods will be called, element's text will never change.
|
1598
1831
|
Runs under element's scope.
|
1599
|
-
|
1832
|
+
_Parameters:_
|
1833
|
+
|
1834
|
+
* `value` current value to be displayed
|
1835
|
+
* `response` server response (if display called after ajax submit), since 1.4.0
|
1836
|
+
|
1837
|
+
For **inputs with source** (select, checklist) parameters are different:
|
1838
|
+
|
1839
|
+
* `value` current value to be displayed
|
1840
|
+
* `sourceData` array of items for current input (e.g. dropdown items)
|
1841
|
+
* `response` server response (if display called after ajax submit), since 1.4.0
|
1842
|
+
|
1843
|
+
To get currently selected items use `$.fn.editableutils.itemsByValue(value, sourceData)`.
|
1600
1844
|
|
1601
1845
|
@property display
|
1602
1846
|
@type function|boolean
|
@@ -1604,8 +1848,16 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1604
1848
|
@since 1.2.0
|
1605
1849
|
@example
|
1606
1850
|
display: function(value, sourceData) {
|
1607
|
-
|
1608
|
-
|
1851
|
+
//display checklist as comma-separated values
|
1852
|
+
var html = [],
|
1853
|
+
checked = $.fn.editableutils.itemsByValue(value, sourceData);
|
1854
|
+
|
1855
|
+
if(checked.length) {
|
1856
|
+
$.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
|
1857
|
+
$(this).html(html.join(', '));
|
1858
|
+
} else {
|
1859
|
+
$(this).empty();
|
1860
|
+
}
|
1609
1861
|
}
|
1610
1862
|
**/
|
1611
1863
|
display: null
|
@@ -1635,26 +1887,27 @@ To create your own input you can inherit from this class.
|
|
1635
1887
|
**/
|
1636
1888
|
init: function(type, options, defaults) {
|
1637
1889
|
this.type = type;
|
1638
|
-
this.options = $.extend({}, defaults, options);
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1890
|
+
this.options = $.extend({}, defaults, options);
|
1891
|
+
},
|
1892
|
+
|
1893
|
+
/*
|
1894
|
+
this method called before render to init $tpl that is inserted in DOM
|
1895
|
+
*/
|
1896
|
+
prerender: function() {
|
1897
|
+
this.$tpl = $(this.options.tpl); //whole tpl as jquery object
|
1898
|
+
this.$input = this.$tpl; //control itself, can be changed in render method
|
1899
|
+
this.$clear = null; //clear button
|
1900
|
+
this.error = null; //error message, if input cannot be rendered
|
1642
1901
|
},
|
1643
1902
|
|
1644
1903
|
/**
|
1645
1904
|
Renders input from tpl. Can return jQuery deferred object.
|
1905
|
+
Can be overwritten in child objects
|
1646
1906
|
|
1647
1907
|
@method render()
|
1648
1908
|
**/
|
1649
1909
|
render: function() {
|
1650
|
-
|
1651
|
-
if(this.options.inputclass) {
|
1652
|
-
this.$input.addClass(this.options.inputclass);
|
1653
|
-
}
|
1654
|
-
|
1655
|
-
if (this.options.placeholder) {
|
1656
|
-
this.$input.attr('placeholder', this.options.placeholder);
|
1657
|
-
}
|
1910
|
+
|
1658
1911
|
},
|
1659
1912
|
|
1660
1913
|
/**
|
@@ -1691,7 +1944,7 @@ To create your own input you can inherit from this class.
|
|
1691
1944
|
},
|
1692
1945
|
|
1693
1946
|
/**
|
1694
|
-
Converts string received from server into value.
|
1947
|
+
Converts string received from server into value. Usually from `data-value` attribute.
|
1695
1948
|
|
1696
1949
|
@method str2value(str)
|
1697
1950
|
@param {string} str
|
@@ -1702,7 +1955,7 @@ To create your own input you can inherit from this class.
|
|
1702
1955
|
},
|
1703
1956
|
|
1704
1957
|
/**
|
1705
|
-
Converts value for submitting to server
|
1958
|
+
Converts value for submitting to server. Result can be string or object.
|
1706
1959
|
|
1707
1960
|
@method value2submit(value)
|
1708
1961
|
@param {mixed} value
|
@@ -1763,7 +2016,25 @@ To create your own input you can inherit from this class.
|
|
1763
2016
|
**/
|
1764
2017
|
autosubmit: function() {
|
1765
2018
|
|
2019
|
+
},
|
2020
|
+
|
2021
|
+
// -------- helper functions --------
|
2022
|
+
setClass: function() {
|
2023
|
+
if(this.options.inputclass) {
|
2024
|
+
this.$input.addClass(this.options.inputclass);
|
2025
|
+
}
|
2026
|
+
},
|
2027
|
+
|
2028
|
+
setAttr: function(attr) {
|
2029
|
+
if (this.options[attr]) {
|
2030
|
+
this.$input.attr(attr, this.options[attr]);
|
2031
|
+
}
|
2032
|
+
},
|
2033
|
+
|
2034
|
+
option: function(key, value) {
|
2035
|
+
this.options[key] = value;
|
1766
2036
|
}
|
2037
|
+
|
1767
2038
|
};
|
1768
2039
|
|
1769
2040
|
AbstractInput.defaults = {
|
@@ -1813,11 +2084,9 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1813
2084
|
|
1814
2085
|
$.extend(List.prototype, {
|
1815
2086
|
render: function () {
|
1816
|
-
List.superclass.render.call(this);
|
1817
2087
|
var deferred = $.Deferred();
|
2088
|
+
|
1818
2089
|
this.error = null;
|
1819
|
-
this.sourceData = null;
|
1820
|
-
this.prependData = null;
|
1821
2090
|
this.onSourceReady(function () {
|
1822
2091
|
this.renderList();
|
1823
2092
|
deferred.resolve();
|
@@ -1833,20 +2102,24 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1833
2102
|
return null; //can't set value by text
|
1834
2103
|
},
|
1835
2104
|
|
1836
|
-
value2html: function (value, element, display) {
|
1837
|
-
var deferred = $.Deferred()
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
2105
|
+
value2html: function (value, element, display, response) {
|
2106
|
+
var deferred = $.Deferred(),
|
2107
|
+
success = function () {
|
2108
|
+
if(typeof display === 'function') {
|
2109
|
+
//custom display method
|
2110
|
+
display.call(element, value, this.sourceData, response);
|
2111
|
+
} else {
|
2112
|
+
this.value2htmlFinal(value, element);
|
2113
|
+
}
|
2114
|
+
deferred.resolve();
|
2115
|
+
};
|
2116
|
+
|
2117
|
+
//for null value just call success without loading source
|
2118
|
+
if(value === null) {
|
2119
|
+
success.call(this);
|
2120
|
+
} else {
|
2121
|
+
this.onSourceReady(success, function () { deferred.resolve(); });
|
2122
|
+
}
|
1850
2123
|
|
1851
2124
|
return deferred.promise();
|
1852
2125
|
},
|
@@ -1872,7 +2145,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1872
2145
|
if (typeof this.options.source === 'string') {
|
1873
2146
|
//try to get from cache
|
1874
2147
|
if(this.options.sourceCache) {
|
1875
|
-
var cacheID = this.options.source
|
2148
|
+
var cacheID = this.options.source,
|
1876
2149
|
cache;
|
1877
2150
|
|
1878
2151
|
if (!$(document).data(cacheID)) {
|
@@ -1883,11 +2156,13 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1883
2156
|
//check for cached data
|
1884
2157
|
if (cache.loading === false && cache.sourceData) { //take source from cache
|
1885
2158
|
this.sourceData = cache.sourceData;
|
2159
|
+
this.doPrepend();
|
1886
2160
|
success.call(this);
|
1887
2161
|
return;
|
1888
2162
|
} else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
|
1889
2163
|
cache.callbacks.push($.proxy(function () {
|
1890
2164
|
this.sourceData = cache.sourceData;
|
2165
|
+
this.doPrepend();
|
1891
2166
|
success.call(this);
|
1892
2167
|
}, this));
|
1893
2168
|
|
@@ -1906,7 +2181,6 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1906
2181
|
url: this.options.source,
|
1907
2182
|
type: 'get',
|
1908
2183
|
cache: false,
|
1909
|
-
data: this.options.name ? {name: this.options.name} : {},
|
1910
2184
|
dataType: 'json',
|
1911
2185
|
success: $.proxy(function (data) {
|
1912
2186
|
if(cache) {
|
@@ -1914,17 +2188,19 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1914
2188
|
}
|
1915
2189
|
this.sourceData = this.makeArray(data);
|
1916
2190
|
if($.isArray(this.sourceData)) {
|
1917
|
-
this.doPrepend();
|
1918
|
-
success.call(this);
|
1919
2191
|
if(cache) {
|
1920
2192
|
//store result in cache
|
1921
2193
|
cache.sourceData = this.sourceData;
|
1922
|
-
|
2194
|
+
//run success callbacks for other fields waiting for this source
|
2195
|
+
$.each(cache.callbacks, function () { this.call(); });
|
1923
2196
|
}
|
2197
|
+
this.doPrepend();
|
2198
|
+
success.call(this);
|
1924
2199
|
} else {
|
1925
2200
|
error.call(this);
|
1926
2201
|
if(cache) {
|
1927
|
-
|
2202
|
+
//run error callbacks for other fields waiting for this source
|
2203
|
+
$.each(cache.err_callbacks, function () { this.call(); });
|
1928
2204
|
}
|
1929
2205
|
}
|
1930
2206
|
}, this),
|
@@ -1937,8 +2213,13 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1937
2213
|
}
|
1938
2214
|
}, this)
|
1939
2215
|
});
|
1940
|
-
} else { //options as json/array
|
1941
|
-
|
2216
|
+
} else { //options as json/array/function
|
2217
|
+
if (typeof this.options.source === 'function') {
|
2218
|
+
this.sourceData = this.makeArray(this.options.source());
|
2219
|
+
} else {
|
2220
|
+
this.sourceData = this.makeArray(this.options.source);
|
2221
|
+
}
|
2222
|
+
|
1942
2223
|
if($.isArray(this.sourceData)) {
|
1943
2224
|
this.doPrepend();
|
1944
2225
|
success.call(this);
|
@@ -1959,7 +2240,11 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
1959
2240
|
if (typeof this.options.prepend === 'string') {
|
1960
2241
|
this.options.prepend = {'': this.options.prepend};
|
1961
2242
|
}
|
1962
|
-
|
2243
|
+
if (typeof this.options.prepend === 'function') {
|
2244
|
+
this.prependData = this.makeArray(this.options.prepend());
|
2245
|
+
} else {
|
2246
|
+
this.prependData = this.makeArray(this.options.prepend);
|
2247
|
+
}
|
1963
2248
|
}
|
1964
2249
|
|
1965
2250
|
if($.isArray(this.prependData) && $.isArray(this.sourceData)) {
|
@@ -2021,41 +2306,41 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2021
2306
|
return result;
|
2022
2307
|
},
|
2023
2308
|
|
2024
|
-
|
2025
|
-
|
2026
|
-
if(
|
2027
|
-
|
2028
|
-
/*jshint eqeqeq: false*/
|
2029
|
-
if(this.sourceData[i].value == val) {
|
2030
|
-
/*jshint eqeqeq: true*/
|
2031
|
-
return this.sourceData[i];
|
2032
|
-
}
|
2033
|
-
}
|
2309
|
+
option: function(key, value) {
|
2310
|
+
this.options[key] = value;
|
2311
|
+
if(key === 'source') {
|
2312
|
+
this.sourceData = null;
|
2034
2313
|
}
|
2314
|
+
if(key === 'prepend') {
|
2315
|
+
this.prependData = null;
|
2316
|
+
}
|
2035
2317
|
}
|
2036
2318
|
|
2037
2319
|
});
|
2038
2320
|
|
2039
2321
|
List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
2040
2322
|
/**
|
2041
|
-
Source data for list.
|
2042
|
-
|
2043
|
-
For compability
|
2044
|
-
If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option.
|
2323
|
+
Source data for list.
|
2324
|
+
If **array** - it should be in format: `[{value: 1, text: "text1"}, {...}]`
|
2325
|
+
For compability, object format is also supported: `{"1": "text1", "2": "text2" ...}` but it does not guarantee elements order.
|
2045
2326
|
|
2327
|
+
If **string** - considered ajax url to load items. In that case results will be cached for fields with the same source and name. See also `sourceCache` option.
|
2328
|
+
|
2329
|
+
If **function**, it should return data in format above (since 1.4.0).
|
2330
|
+
|
2046
2331
|
@property source
|
2047
|
-
@type string|array|object
|
2332
|
+
@type string | array | object | function
|
2048
2333
|
@default null
|
2049
2334
|
**/
|
2050
|
-
source:null,
|
2335
|
+
source: null,
|
2051
2336
|
/**
|
2052
2337
|
Data automatically prepended to the beginning of dropdown list.
|
2053
2338
|
|
2054
2339
|
@property prepend
|
2055
|
-
@type string|array|object
|
2340
|
+
@type string | array | object | function
|
2056
2341
|
@default false
|
2057
2342
|
**/
|
2058
|
-
prepend:false,
|
2343
|
+
prepend: false,
|
2059
2344
|
/**
|
2060
2345
|
Error message when list cannot be loaded (e.g. ajax error)
|
2061
2346
|
|
@@ -2079,6 +2364,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2079
2364
|
$.fn.editabletypes.list = List;
|
2080
2365
|
|
2081
2366
|
}(window.jQuery));
|
2367
|
+
|
2082
2368
|
/**
|
2083
2369
|
Text input
|
2084
2370
|
|
@@ -2104,11 +2390,64 @@ $(function(){
|
|
2104
2390
|
$.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput);
|
2105
2391
|
|
2106
2392
|
$.extend(Text.prototype, {
|
2107
|
-
|
2108
|
-
|
2393
|
+
render: function() {
|
2394
|
+
this.renderClear();
|
2395
|
+
this.setClass();
|
2396
|
+
this.setAttr('placeholder');
|
2397
|
+
},
|
2398
|
+
|
2399
|
+
activate: function() {
|
2400
|
+
if(this.$input.is(':visible')) {
|
2109
2401
|
this.$input.focus();
|
2110
2402
|
$.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
2403
|
+
if(this.toggleClear) {
|
2404
|
+
this.toggleClear();
|
2405
|
+
}
|
2406
|
+
}
|
2407
|
+
},
|
2408
|
+
|
2409
|
+
//render clear button
|
2410
|
+
renderClear: function() {
|
2411
|
+
if (this.options.clear) {
|
2412
|
+
this.$clear = $('<span class="editable-clear-x"></span>');
|
2413
|
+
this.$input.after(this.$clear)
|
2414
|
+
.css('padding-right', 20)
|
2415
|
+
.keyup($.proxy(this.toggleClear, this))
|
2416
|
+
.parent().css('position', 'relative');
|
2417
|
+
|
2418
|
+
this.$clear.click($.proxy(function(){
|
2419
|
+
this.$clear.hide();
|
2420
|
+
this.$input.val('').focus();
|
2421
|
+
}, this));
|
2422
|
+
}
|
2423
|
+
},
|
2424
|
+
|
2425
|
+
postrender: function() {
|
2426
|
+
if(this.$clear) {
|
2427
|
+
//can position clear button only here, when form is shown and height can be calculated
|
2428
|
+
var h = this.$input.outerHeight() || 20,
|
2429
|
+
delta = (h - this.$clear.height()) / 2;
|
2430
|
+
|
2431
|
+
//workaround for plain-popup
|
2432
|
+
if(delta < 3) {
|
2433
|
+
delta = 3;
|
2434
|
+
}
|
2435
|
+
|
2436
|
+
this.$clear.css({top: delta, right: delta});
|
2437
|
+
}
|
2438
|
+
},
|
2439
|
+
|
2440
|
+
//show / hide clear button
|
2441
|
+
toggleClear: function() {
|
2442
|
+
if(!this.$clear) {
|
2443
|
+
return;
|
2111
2444
|
}
|
2445
|
+
|
2446
|
+
if(this.$input.val()) {
|
2447
|
+
this.$clear.show();
|
2448
|
+
} else {
|
2449
|
+
this.$clear.hide();
|
2450
|
+
}
|
2112
2451
|
}
|
2113
2452
|
});
|
2114
2453
|
|
@@ -2125,7 +2464,16 @@ $(function(){
|
|
2125
2464
|
@type string
|
2126
2465
|
@default null
|
2127
2466
|
**/
|
2128
|
-
placeholder: null
|
2467
|
+
placeholder: null,
|
2468
|
+
|
2469
|
+
/**
|
2470
|
+
Whether to show `clear` button
|
2471
|
+
|
2472
|
+
@property clear
|
2473
|
+
@type boolean
|
2474
|
+
@default true
|
2475
|
+
**/
|
2476
|
+
clear: true
|
2129
2477
|
});
|
2130
2478
|
|
2131
2479
|
$.fn.editabletypes.text = Text;
|
@@ -2144,7 +2492,8 @@ Textarea input
|
|
2144
2492
|
$(function(){
|
2145
2493
|
$('#comments').editable({
|
2146
2494
|
url: '/post',
|
2147
|
-
title: 'Enter comments'
|
2495
|
+
title: 'Enter comments',
|
2496
|
+
rows: 10
|
2148
2497
|
});
|
2149
2498
|
});
|
2150
2499
|
</script>
|
@@ -2159,8 +2508,10 @@ $(function(){
|
|
2159
2508
|
|
2160
2509
|
$.extend(Textarea.prototype, {
|
2161
2510
|
render: function () {
|
2162
|
-
|
2163
|
-
|
2511
|
+
this.setClass();
|
2512
|
+
this.setAttr('placeholder');
|
2513
|
+
this.setAttr('rows');
|
2514
|
+
|
2164
2515
|
//ctrl + enter
|
2165
2516
|
this.$input.keydown(function (e) {
|
2166
2517
|
if (e.ctrlKey && e.which === 13) {
|
@@ -2185,43 +2536,56 @@ $(function(){
|
|
2185
2536
|
if(!html) {
|
2186
2537
|
return '';
|
2187
2538
|
}
|
2539
|
+
|
2540
|
+
var regex = new RegExp(String.fromCharCode(10), 'g');
|
2188
2541
|
var lines = html.split(/<br\s*\/?>/i);
|
2189
2542
|
for (var i = 0; i < lines.length; i++) {
|
2190
|
-
|
2543
|
+
var text = $('<div>').html(lines[i]).text();
|
2544
|
+
|
2545
|
+
// Remove newline characters (\n) to avoid them being converted by value2html() method
|
2546
|
+
// thus adding extra <br> tags
|
2547
|
+
text = text.replace(regex, '');
|
2548
|
+
|
2549
|
+
lines[i] = text;
|
2191
2550
|
}
|
2192
|
-
return lines.join("\n");
|
2193
|
-
},
|
2551
|
+
return lines.join("\n");
|
2552
|
+
},
|
2194
2553
|
|
2195
2554
|
activate: function() {
|
2196
|
-
|
2197
|
-
|
2198
|
-
this.$input.focus();
|
2199
|
-
}
|
2200
|
-
}
|
2555
|
+
$.fn.editabletypes.text.prototype.activate.call(this);
|
2556
|
+
}
|
2201
2557
|
});
|
2202
2558
|
|
2203
2559
|
Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
2204
2560
|
/**
|
2205
|
-
@property tpl
|
2561
|
+
@property tpl
|
2206
2562
|
@default <textarea></textarea>
|
2207
|
-
**/
|
2563
|
+
**/
|
2208
2564
|
tpl:'<textarea></textarea>',
|
2209
2565
|
/**
|
2210
|
-
@property inputclass
|
2566
|
+
@property inputclass
|
2211
2567
|
@default input-large
|
2212
|
-
**/
|
2568
|
+
**/
|
2213
2569
|
inputclass: 'input-large',
|
2214
2570
|
/**
|
2215
2571
|
Placeholder attribute of input. Shown when input is empty.
|
2216
2572
|
|
2217
|
-
@property placeholder
|
2573
|
+
@property placeholder
|
2218
2574
|
@type string
|
2219
2575
|
@default null
|
2220
|
-
**/
|
2221
|
-
placeholder: null
|
2576
|
+
**/
|
2577
|
+
placeholder: null,
|
2578
|
+
/**
|
2579
|
+
Number of rows in textarea
|
2580
|
+
|
2581
|
+
@property rows
|
2582
|
+
@type integer
|
2583
|
+
@default 7
|
2584
|
+
**/
|
2585
|
+
rows: 7
|
2222
2586
|
});
|
2223
2587
|
|
2224
|
-
$.fn.editabletypes.textarea = Textarea;
|
2588
|
+
$.fn.editabletypes.textarea = Textarea;
|
2225
2589
|
|
2226
2590
|
}(window.jQuery));
|
2227
2591
|
|
@@ -2257,6 +2621,8 @@ $(function(){
|
|
2257
2621
|
|
2258
2622
|
$.extend(Select.prototype, {
|
2259
2623
|
renderList: function() {
|
2624
|
+
this.$input.empty();
|
2625
|
+
|
2260
2626
|
if(!$.isArray(this.sourceData)) {
|
2261
2627
|
return;
|
2262
2628
|
}
|
@@ -2265,6 +2631,8 @@ $(function(){
|
|
2265
2631
|
this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
|
2266
2632
|
}
|
2267
2633
|
|
2634
|
+
this.setClass();
|
2635
|
+
|
2268
2636
|
//enter submit
|
2269
2637
|
this.$input.on('keydown.editable', function (e) {
|
2270
2638
|
if (e.which === 13) {
|
@@ -2274,11 +2642,14 @@ $(function(){
|
|
2274
2642
|
},
|
2275
2643
|
|
2276
2644
|
value2htmlFinal: function(value, element) {
|
2277
|
-
var text = '',
|
2278
|
-
|
2279
|
-
|
2645
|
+
var text = '',
|
2646
|
+
items = $.fn.editableutils.itemsByValue(value, this.sourceData);
|
2647
|
+
|
2648
|
+
if(items.length) {
|
2649
|
+
text = items[0].text;
|
2280
2650
|
}
|
2281
|
-
|
2651
|
+
|
2652
|
+
$(element).text(text);
|
2282
2653
|
},
|
2283
2654
|
|
2284
2655
|
autosubmit: function() {
|
@@ -2333,6 +2704,9 @@ $(function(){
|
|
2333
2704
|
$.extend(Checklist.prototype, {
|
2334
2705
|
renderList: function() {
|
2335
2706
|
var $label, $div;
|
2707
|
+
|
2708
|
+
this.$tpl.empty();
|
2709
|
+
|
2336
2710
|
if(!$.isArray(this.sourceData)) {
|
2337
2711
|
return;
|
2338
2712
|
}
|
@@ -2345,8 +2719,11 @@ $(function(){
|
|
2345
2719
|
}))
|
2346
2720
|
.append($('<span>').text(' '+this.sourceData[i].text));
|
2347
2721
|
|
2348
|
-
$('<div>').append($label).appendTo(this.$
|
2722
|
+
$('<div>').append($label).appendTo(this.$tpl);
|
2349
2723
|
}
|
2724
|
+
|
2725
|
+
this.$input = this.$tpl.find('input[type="checkbox"]');
|
2726
|
+
this.setClass();
|
2350
2727
|
},
|
2351
2728
|
|
2352
2729
|
value2str: function(value) {
|
@@ -2367,10 +2744,9 @@ $(function(){
|
|
2367
2744
|
|
2368
2745
|
//set checked on required checkboxes
|
2369
2746
|
value2input: function(value) {
|
2370
|
-
|
2371
|
-
$checks.removeAttr('checked');
|
2747
|
+
this.$input.removeAttr('checked');
|
2372
2748
|
if($.isArray(value) && value.length) {
|
2373
|
-
|
2749
|
+
this.$input.each(function(i, el) {
|
2374
2750
|
var $el = $(el);
|
2375
2751
|
// cannot use $.inArray as it performs strict comparison
|
2376
2752
|
$.each(value, function(j, val){
|
@@ -2386,7 +2762,7 @@ $(function(){
|
|
2386
2762
|
|
2387
2763
|
input2value: function() {
|
2388
2764
|
var checked = [];
|
2389
|
-
this.$input.
|
2765
|
+
this.$input.filter(':checked').each(function(i, el) {
|
2390
2766
|
checked.push($(el).val());
|
2391
2767
|
});
|
2392
2768
|
return checked;
|
@@ -2395,11 +2771,8 @@ $(function(){
|
|
2395
2771
|
//collect text of checked boxes
|
2396
2772
|
value2htmlFinal: function(value, element) {
|
2397
2773
|
var html = [],
|
2398
|
-
|
2399
|
-
|
2400
|
-
return $.grep(value, function(v){ return v == o.value; }).length;
|
2401
|
-
});
|
2402
|
-
/*jslint eqeq: false*/
|
2774
|
+
checked = $.fn.editableutils.itemsByValue(value, this.sourceData);
|
2775
|
+
|
2403
2776
|
if(checked.length) {
|
2404
2777
|
$.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
|
2405
2778
|
$(element).html(html.join('<br>'));
|
@@ -2409,11 +2782,11 @@ $(function(){
|
|
2409
2782
|
},
|
2410
2783
|
|
2411
2784
|
activate: function() {
|
2412
|
-
this.$input.
|
2785
|
+
this.$input.first().focus();
|
2413
2786
|
},
|
2414
2787
|
|
2415
2788
|
autosubmit: function() {
|
2416
|
-
this.$input.
|
2789
|
+
this.$input.on('keydown', function(e){
|
2417
2790
|
if (e.which === 13) {
|
2418
2791
|
$(this).closest('form').submit();
|
2419
2792
|
}
|
@@ -2426,21 +2799,21 @@ $(function(){
|
|
2426
2799
|
@property tpl
|
2427
2800
|
@default <div></div>
|
2428
2801
|
**/
|
2429
|
-
tpl:'<div></div>',
|
2802
|
+
tpl:'<div class="editable-checklist"></div>',
|
2430
2803
|
|
2431
2804
|
/**
|
2432
2805
|
@property inputclass
|
2433
2806
|
@type string
|
2434
|
-
@default
|
2807
|
+
@default null
|
2435
2808
|
**/
|
2436
|
-
inputclass:
|
2809
|
+
inputclass: null,
|
2437
2810
|
|
2438
2811
|
/**
|
2439
|
-
Separator of values when reading from
|
2812
|
+
Separator of values when reading from `data-value` attribute
|
2440
2813
|
|
2441
2814
|
@property separator
|
2442
2815
|
@type string
|
2443
|
-
@default ',
|
2816
|
+
@default ','
|
2444
2817
|
**/
|
2445
2818
|
separator: ','
|
2446
2819
|
});
|
@@ -2571,18 +2944,9 @@ Number
|
|
2571
2944
|
$.extend(NumberInput.prototype, {
|
2572
2945
|
render: function () {
|
2573
2946
|
NumberInput.superclass.render.call(this);
|
2574
|
-
|
2575
|
-
|
2576
|
-
|
2577
|
-
}
|
2578
|
-
|
2579
|
-
if (this.options.max !== null) {
|
2580
|
-
this.$input.attr('max', this.options.max);
|
2581
|
-
}
|
2582
|
-
|
2583
|
-
if (this.options.step !== null) {
|
2584
|
-
this.$input.attr('step', this.options.step);
|
2585
|
-
}
|
2947
|
+
this.setAttr('min');
|
2948
|
+
this.setAttr('max');
|
2949
|
+
this.setAttr('step');
|
2586
2950
|
}
|
2587
2951
|
});
|
2588
2952
|
NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
|
@@ -2606,29 +2970,19 @@ Range (inherit from number)
|
|
2606
2970
|
$.fn.editableutils.inherit(Range, $.fn.editabletypes.number);
|
2607
2971
|
$.extend(Range.prototype, {
|
2608
2972
|
render: function () {
|
2609
|
-
this.$input =
|
2610
|
-
var $slider = this.$input.filter('input');
|
2611
|
-
if(this.options.inputclass) {
|
2612
|
-
$slider.addClass(this.options.inputclass);
|
2613
|
-
}
|
2614
|
-
if (this.options.min !== null) {
|
2615
|
-
$slider.attr('min', this.options.min);
|
2616
|
-
}
|
2617
|
-
|
2618
|
-
if (this.options.max !== null) {
|
2619
|
-
$slider.attr('max', this.options.max);
|
2620
|
-
}
|
2973
|
+
this.$input = this.$tpl.filter('input');
|
2621
2974
|
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2975
|
+
this.setClass();
|
2976
|
+
this.setAttr('min');
|
2977
|
+
this.setAttr('max');
|
2978
|
+
this.setAttr('step');
|
2625
2979
|
|
2626
|
-
|
2980
|
+
this.$input.on('input', function(){
|
2627
2981
|
$(this).siblings('output').text($(this).val());
|
2628
2982
|
});
|
2629
2983
|
},
|
2630
2984
|
activate: function() {
|
2631
|
-
this.$input.
|
2985
|
+
this.$input.focus();
|
2632
2986
|
}
|
2633
2987
|
});
|
2634
2988
|
Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, {
|
@@ -2637,6 +2991,590 @@ Range (inherit from number)
|
|
2637
2991
|
});
|
2638
2992
|
$.fn.editabletypes.range = Range;
|
2639
2993
|
}(window.jQuery));
|
2994
|
+
/**
|
2995
|
+
* Combodate - 1.0.1
|
2996
|
+
* Dropdown date and time picker.
|
2997
|
+
* Converts text input into dropdowns to pick day, month, year, hour, minute and second.
|
2998
|
+
* Uses momentjs as datetime library http://momentjs.com.
|
2999
|
+
* For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang
|
3000
|
+
*
|
3001
|
+
* Author: Vitaliy Potapov
|
3002
|
+
* Project page: http://github.com/vitalets/combodate
|
3003
|
+
* Copyright (c) 2012 Vitaliy Potapov. Released under MIT License.
|
3004
|
+
**/
|
3005
|
+
(function ($) {
|
3006
|
+
|
3007
|
+
var Combodate = function (element, options) {
|
3008
|
+
this.$element = $(element);
|
3009
|
+
if(!this.$element.is('input')) {
|
3010
|
+
$.error('Combodate should be applied to INPUT element');
|
3011
|
+
return;
|
3012
|
+
}
|
3013
|
+
this.options = $.extend({}, $.fn.combodate.defaults, options, this.$element.data());
|
3014
|
+
this.init();
|
3015
|
+
};
|
3016
|
+
|
3017
|
+
Combodate.prototype = {
|
3018
|
+
constructor: Combodate,
|
3019
|
+
init: function () {
|
3020
|
+
this.map = {
|
3021
|
+
//key regexp moment.method
|
3022
|
+
day: ['D', 'date'],
|
3023
|
+
month: ['M', 'month'],
|
3024
|
+
year: ['Y', 'year'],
|
3025
|
+
hour: ['[Hh]', 'hours'],
|
3026
|
+
minute: ['m', 'minutes'],
|
3027
|
+
second: ['s', 'seconds'],
|
3028
|
+
ampm: ['[Aa]', '']
|
3029
|
+
};
|
3030
|
+
|
3031
|
+
this.$widget = $('<span class="combodate"></span>').html(this.getTemplate());
|
3032
|
+
|
3033
|
+
this.initCombos();
|
3034
|
+
|
3035
|
+
//update original input on change
|
3036
|
+
this.$widget.on('change', 'select', $.proxy(function(){
|
3037
|
+
this.$element.val(this.getValue());
|
3038
|
+
}, this));
|
3039
|
+
|
3040
|
+
this.$widget.find('select').css('width', 'auto');
|
3041
|
+
|
3042
|
+
//hide original input and insert widget
|
3043
|
+
this.$element.hide().after(this.$widget);
|
3044
|
+
|
3045
|
+
//set initial value
|
3046
|
+
this.setValue(this.$element.val() || this.options.value);
|
3047
|
+
},
|
3048
|
+
|
3049
|
+
/*
|
3050
|
+
Replace tokens in template with <select> elements
|
3051
|
+
*/
|
3052
|
+
getTemplate: function() {
|
3053
|
+
var tpl = this.options.template;
|
3054
|
+
|
3055
|
+
//first pass
|
3056
|
+
$.each(this.map, function(k, v) {
|
3057
|
+
v = v[0];
|
3058
|
+
var r = new RegExp(v+'+'),
|
3059
|
+
token = v.length > 1 ? v.substring(1, 2) : v;
|
3060
|
+
|
3061
|
+
tpl = tpl.replace(r, '{'+token+'}');
|
3062
|
+
});
|
3063
|
+
|
3064
|
+
//replace spaces with
|
3065
|
+
tpl = tpl.replace(/ /g, ' ');
|
3066
|
+
|
3067
|
+
//second pass
|
3068
|
+
$.each(this.map, function(k, v) {
|
3069
|
+
v = v[0];
|
3070
|
+
var token = v.length > 1 ? v.substring(1, 2) : v;
|
3071
|
+
|
3072
|
+
tpl = tpl.replace('{'+token+'}', '<select class="'+k+'"></select>');
|
3073
|
+
});
|
3074
|
+
|
3075
|
+
return tpl;
|
3076
|
+
},
|
3077
|
+
|
3078
|
+
/*
|
3079
|
+
Initialize combos that presents in template
|
3080
|
+
*/
|
3081
|
+
initCombos: function() {
|
3082
|
+
var that = this;
|
3083
|
+
$.each(this.map, function(k, v) {
|
3084
|
+
var $c = that.$widget.find('.'+k), f, items;
|
3085
|
+
if($c.length) {
|
3086
|
+
that['$'+k] = $c; //set properties like this.$day, this.$month etc.
|
3087
|
+
f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1); //define method name to fill items, e.g `fillDays`
|
3088
|
+
items = that[f]();
|
3089
|
+
that['$'+k].html(that.renderItems(items));
|
3090
|
+
}
|
3091
|
+
});
|
3092
|
+
},
|
3093
|
+
|
3094
|
+
/*
|
3095
|
+
Initialize items of combos. Handles `firstItem` option
|
3096
|
+
*/
|
3097
|
+
initItems: function(key) {
|
3098
|
+
var values = [];
|
3099
|
+
if(this.options.firstItem === 'name') {
|
3100
|
+
var header = typeof moment.relativeTime[key] === 'function' ? moment.relativeTime[key](1, true, key, false) : moment.relativeTime[key];
|
3101
|
+
//take last entry (see momentjs lang files structure)
|
3102
|
+
header = header.split(' ').reverse()[0];
|
3103
|
+
values.push(['', header]);
|
3104
|
+
} else if(this.options.firstItem === 'empty') {
|
3105
|
+
values.push(['', '']);
|
3106
|
+
}
|
3107
|
+
return values;
|
3108
|
+
},
|
3109
|
+
|
3110
|
+
/*
|
3111
|
+
render items to string of <option> tags
|
3112
|
+
*/
|
3113
|
+
renderItems: function(items) {
|
3114
|
+
var str = [];
|
3115
|
+
for(var i=0; i<items.length; i++) {
|
3116
|
+
str.push('<option value="'+items[i][0]+'">'+items[i][1]+'</option>');
|
3117
|
+
}
|
3118
|
+
return str.join("\n");
|
3119
|
+
},
|
3120
|
+
|
3121
|
+
/*
|
3122
|
+
fill day
|
3123
|
+
*/
|
3124
|
+
fillDay: function() {
|
3125
|
+
var items = this.initItems('d'), name, i,
|
3126
|
+
twoDigit = this.options.template.indexOf('DD') !== -1;
|
3127
|
+
|
3128
|
+
for(i=1; i<=31; i++) {
|
3129
|
+
name = twoDigit ? this.leadZero(i) : i;
|
3130
|
+
items.push([i, name]);
|
3131
|
+
}
|
3132
|
+
return items;
|
3133
|
+
},
|
3134
|
+
|
3135
|
+
/*
|
3136
|
+
fill month
|
3137
|
+
*/
|
3138
|
+
fillMonth: function() {
|
3139
|
+
var items = this.initItems('M'), name, i,
|
3140
|
+
longNames = this.options.template.indexOf('MMMM') !== -1,
|
3141
|
+
shortNames = this.options.template.indexOf('MMM') !== -1,
|
3142
|
+
twoDigit = this.options.template.indexOf('MM') !== -1;
|
3143
|
+
|
3144
|
+
for(i=0; i<=11; i++) {
|
3145
|
+
if(longNames) {
|
3146
|
+
name = moment.months[i];
|
3147
|
+
} else if(shortNames) {
|
3148
|
+
name = moment.monthsShort[i];
|
3149
|
+
} else if(twoDigit) {
|
3150
|
+
name = this.leadZero(i+1);
|
3151
|
+
} else {
|
3152
|
+
name = i+1;
|
3153
|
+
}
|
3154
|
+
items.push([i, name]);
|
3155
|
+
}
|
3156
|
+
return items;
|
3157
|
+
},
|
3158
|
+
|
3159
|
+
/*
|
3160
|
+
fill year
|
3161
|
+
*/
|
3162
|
+
fillYear: function() {
|
3163
|
+
var items = this.initItems('y'), name, i,
|
3164
|
+
longNames = this.options.template.indexOf('YYYY') !== -1;
|
3165
|
+
|
3166
|
+
for(i=this.options.maxYear; i>=this.options.minYear; i--) {
|
3167
|
+
name = longNames ? i : (i+'').substring(2);
|
3168
|
+
items.push([i, name]);
|
3169
|
+
}
|
3170
|
+
return items;
|
3171
|
+
},
|
3172
|
+
|
3173
|
+
/*
|
3174
|
+
fill hour
|
3175
|
+
*/
|
3176
|
+
fillHour: function() {
|
3177
|
+
var items = this.initItems('h'), name, i,
|
3178
|
+
h12 = this.options.template.indexOf('h') !== -1,
|
3179
|
+
h24 = this.options.template.indexOf('H') !== -1,
|
3180
|
+
twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1,
|
3181
|
+
max = h12 ? 12 : 23;
|
3182
|
+
|
3183
|
+
for(i=0; i<=max; i++) {
|
3184
|
+
name = twoDigit ? this.leadZero(i) : i;
|
3185
|
+
items.push([i, name]);
|
3186
|
+
}
|
3187
|
+
return items;
|
3188
|
+
},
|
3189
|
+
|
3190
|
+
/*
|
3191
|
+
fill minute
|
3192
|
+
*/
|
3193
|
+
fillMinute: function() {
|
3194
|
+
var items = this.initItems('m'), name, i,
|
3195
|
+
twoDigit = this.options.template.indexOf('mm') !== -1;
|
3196
|
+
|
3197
|
+
for(i=0; i<=59; i+= this.options.minuteStep) {
|
3198
|
+
name = twoDigit ? this.leadZero(i) : i;
|
3199
|
+
items.push([i, name]);
|
3200
|
+
}
|
3201
|
+
return items;
|
3202
|
+
},
|
3203
|
+
|
3204
|
+
/*
|
3205
|
+
fill second
|
3206
|
+
*/
|
3207
|
+
fillSecond: function() {
|
3208
|
+
var items = this.initItems('s'), name, i,
|
3209
|
+
twoDigit = this.options.template.indexOf('ss') !== -1;
|
3210
|
+
|
3211
|
+
for(i=0; i<=59; i+= this.options.secondStep) {
|
3212
|
+
name = twoDigit ? this.leadZero(i) : i;
|
3213
|
+
items.push([i, name]);
|
3214
|
+
}
|
3215
|
+
return items;
|
3216
|
+
},
|
3217
|
+
|
3218
|
+
/*
|
3219
|
+
fill ampm
|
3220
|
+
*/
|
3221
|
+
fillAmpm: function() {
|
3222
|
+
var ampmL = this.options.template.indexOf('a') !== -1,
|
3223
|
+
ampmU = this.options.template.indexOf('A') !== -1,
|
3224
|
+
items = [
|
3225
|
+
['am', ampmL ? 'am' : 'AM'],
|
3226
|
+
['pm', ampmL ? 'pm' : 'PM']
|
3227
|
+
];
|
3228
|
+
return items;
|
3229
|
+
},
|
3230
|
+
|
3231
|
+
/*
|
3232
|
+
Returns current date value.
|
3233
|
+
If format not specified - `options.format` used.
|
3234
|
+
If format = `null` - Moment object returned.
|
3235
|
+
*/
|
3236
|
+
getValue: function(format) {
|
3237
|
+
var dt, values = {},
|
3238
|
+
that = this,
|
3239
|
+
notSelected = false;
|
3240
|
+
|
3241
|
+
//getting selected values
|
3242
|
+
$.each(this.map, function(k, v) {
|
3243
|
+
if(k === 'ampm') {
|
3244
|
+
return;
|
3245
|
+
}
|
3246
|
+
var def = k === 'day' ? 1 : 0;
|
3247
|
+
|
3248
|
+
values[k] = that['$'+k] ? parseInt(that['$'+k].val(), 10) : def;
|
3249
|
+
|
3250
|
+
if(isNaN(values[k])) {
|
3251
|
+
notSelected = true;
|
3252
|
+
return false;
|
3253
|
+
}
|
3254
|
+
});
|
3255
|
+
|
3256
|
+
//if at least one visible combo not selected - return empty string
|
3257
|
+
if(notSelected) {
|
3258
|
+
return '';
|
3259
|
+
}
|
3260
|
+
|
3261
|
+
//convert hours if 12h format
|
3262
|
+
if(this.$ampm) {
|
3263
|
+
values.hour = this.$ampm.val() === 'am' ? values.hour : values.hour+12;
|
3264
|
+
if(values.hour === 24) {
|
3265
|
+
values.hour = 0;
|
3266
|
+
}
|
3267
|
+
}
|
3268
|
+
|
3269
|
+
dt = moment([values.year, values.month, values.day, values.hour, values.minute, values.second]);
|
3270
|
+
|
3271
|
+
//highlight invalid date
|
3272
|
+
this.highlight(dt);
|
3273
|
+
|
3274
|
+
format = format === undefined ? this.options.format : format;
|
3275
|
+
if(format === null) {
|
3276
|
+
return dt.isValid() ? dt : null;
|
3277
|
+
} else {
|
3278
|
+
return dt.isValid() ? dt.format(format) : '';
|
3279
|
+
}
|
3280
|
+
},
|
3281
|
+
|
3282
|
+
setValue: function(value) {
|
3283
|
+
if(!value) {
|
3284
|
+
return;
|
3285
|
+
}
|
3286
|
+
|
3287
|
+
var dt = typeof value === 'string' ? moment(value, this.options.format) : moment(value),
|
3288
|
+
that = this,
|
3289
|
+
values = {};
|
3290
|
+
|
3291
|
+
if(dt.isValid()) {
|
3292
|
+
//read values from date object
|
3293
|
+
$.each(this.map, function(k, v) {
|
3294
|
+
if(k === 'ampm') {
|
3295
|
+
return;
|
3296
|
+
}
|
3297
|
+
values[k] = dt[v[1]]();
|
3298
|
+
});
|
3299
|
+
|
3300
|
+
if(this.$ampm) {
|
3301
|
+
if(values.hour > 12) {
|
3302
|
+
values.hour -= 12;
|
3303
|
+
values.ampm = 'pm';
|
3304
|
+
} else {
|
3305
|
+
values.ampm = 'am';
|
3306
|
+
}
|
3307
|
+
}
|
3308
|
+
|
3309
|
+
$.each(values, function(k, v) {
|
3310
|
+
if(that['$'+k]) {
|
3311
|
+
that['$'+k].val(v);
|
3312
|
+
}
|
3313
|
+
});
|
3314
|
+
|
3315
|
+
this.$element.val(dt.format(this.options.format));
|
3316
|
+
}
|
3317
|
+
},
|
3318
|
+
|
3319
|
+
/*
|
3320
|
+
highlight combos if date is invalid
|
3321
|
+
*/
|
3322
|
+
highlight: function(dt) {
|
3323
|
+
if(!dt.isValid()) {
|
3324
|
+
if(this.options.errorClass) {
|
3325
|
+
this.$widget.addClass(this.options.errorClass);
|
3326
|
+
} else {
|
3327
|
+
//store original border color
|
3328
|
+
if(!this.borderColor) {
|
3329
|
+
this.borderColor = this.$widget.find('select').css('border-color');
|
3330
|
+
}
|
3331
|
+
this.$widget.find('select').css('border-color', 'red');
|
3332
|
+
}
|
3333
|
+
} else {
|
3334
|
+
if(this.options.errorClass) {
|
3335
|
+
this.$widget.removeClass(this.options.errorClass);
|
3336
|
+
} else {
|
3337
|
+
this.$widget.find('select').css('border-color', this.borderColor);
|
3338
|
+
}
|
3339
|
+
}
|
3340
|
+
},
|
3341
|
+
|
3342
|
+
leadZero: function(v) {
|
3343
|
+
return v <= 9 ? '0' + v : v;
|
3344
|
+
},
|
3345
|
+
|
3346
|
+
destroy: function() {
|
3347
|
+
this.$widget.remove();
|
3348
|
+
this.$element.removeData('combodate').show();
|
3349
|
+
}
|
3350
|
+
|
3351
|
+
//todo: clear method
|
3352
|
+
};
|
3353
|
+
|
3354
|
+
$.fn.combodate = function ( option ) {
|
3355
|
+
var d, args = Array.apply(null, arguments);
|
3356
|
+
args.shift();
|
3357
|
+
|
3358
|
+
//getValue returns date as string / object (not jQuery object)
|
3359
|
+
if(option === 'getValue' && this.length && (d = this.eq(0).data('combodate'))) {
|
3360
|
+
return d.getValue.apply(d, args);
|
3361
|
+
}
|
3362
|
+
|
3363
|
+
return this.each(function () {
|
3364
|
+
var $this = $(this),
|
3365
|
+
data = $this.data('combodate'),
|
3366
|
+
options = typeof option == 'object' && option;
|
3367
|
+
if (!data) {
|
3368
|
+
$this.data('combodate', (data = new Combodate(this, options)));
|
3369
|
+
}
|
3370
|
+
if (typeof option == 'string' && typeof data[option] == 'function') {
|
3371
|
+
data[option].apply(data, args);
|
3372
|
+
}
|
3373
|
+
});
|
3374
|
+
};
|
3375
|
+
|
3376
|
+
$.fn.combodate.defaults = {
|
3377
|
+
//in this format value stored in original input
|
3378
|
+
format: 'DD-MM-YYYY HH:mm',
|
3379
|
+
//in this format items in dropdowns are displayed
|
3380
|
+
template: 'D / MMM / YYYY H : mm',
|
3381
|
+
//initial value, can be `new Date()`
|
3382
|
+
value: null,
|
3383
|
+
minYear: 1970,
|
3384
|
+
maxYear: 2015,
|
3385
|
+
minuteStep: 5,
|
3386
|
+
secondStep: 1,
|
3387
|
+
firstItem: 'empty', //'name', 'empty', 'none'
|
3388
|
+
errorClass: null
|
3389
|
+
};
|
3390
|
+
|
3391
|
+
}(window.jQuery));
|
3392
|
+
/**
|
3393
|
+
Combodate input - dropdown date and time picker.
|
3394
|
+
Based on [combodate](http://vitalets.github.com/combodate) plugin. To use it you should manually include [momentjs](http://momentjs.com).
|
3395
|
+
|
3396
|
+
<script src="js/moment.min.js"></script>
|
3397
|
+
|
3398
|
+
Allows to input:
|
3399
|
+
|
3400
|
+
* only date
|
3401
|
+
* only time
|
3402
|
+
* both date and time
|
3403
|
+
|
3404
|
+
Please note, that format is taken from momentjs and **not compatible** with bootstrap-datepicker / jquery UI datepicker.
|
3405
|
+
Internally value stored as `momentjs` object.
|
3406
|
+
|
3407
|
+
@class combodate
|
3408
|
+
@extends abstractinput
|
3409
|
+
@final
|
3410
|
+
@since 1.4.0
|
3411
|
+
@example
|
3412
|
+
<a href="#" id="dob" data-type="combodate" data-pk="1" data-url="/post" data-value="1984-05-15" data-original-title="Select date"></a>
|
3413
|
+
<script>
|
3414
|
+
$(function(){
|
3415
|
+
$('#dob').editable({
|
3416
|
+
format: 'YYYY-MM-DD',
|
3417
|
+
viewformat: 'DD.MM.YYYY',
|
3418
|
+
template: 'D / MMMM / YYYY',
|
3419
|
+
combodate: {
|
3420
|
+
minYear: 2000,
|
3421
|
+
maxYear: 2015,
|
3422
|
+
minuteStep: 1
|
3423
|
+
}
|
3424
|
+
}
|
3425
|
+
});
|
3426
|
+
});
|
3427
|
+
</script>
|
3428
|
+
**/
|
3429
|
+
|
3430
|
+
/*global moment*/
|
3431
|
+
|
3432
|
+
(function ($) {
|
3433
|
+
|
3434
|
+
var Constructor = function (options) {
|
3435
|
+
this.init('combodate', options, Constructor.defaults);
|
3436
|
+
|
3437
|
+
//by default viewformat equals to format
|
3438
|
+
if(!this.options.viewformat) {
|
3439
|
+
this.options.viewformat = this.options.format;
|
3440
|
+
}
|
3441
|
+
|
3442
|
+
//overriding combodate config (as by default jQuery extend() is not recursive)
|
3443
|
+
this.options.combodate = $.extend({}, Constructor.defaults.combodate, options.combodate, {
|
3444
|
+
format: this.options.format,
|
3445
|
+
template: this.options.template
|
3446
|
+
});
|
3447
|
+
};
|
3448
|
+
|
3449
|
+
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
|
3450
|
+
|
3451
|
+
$.extend(Constructor.prototype, {
|
3452
|
+
render: function () {
|
3453
|
+
this.$input.combodate(this.options.combodate);
|
3454
|
+
|
3455
|
+
//"clear" link
|
3456
|
+
/*
|
3457
|
+
if(this.options.clear) {
|
3458
|
+
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
|
3459
|
+
e.preventDefault();
|
3460
|
+
e.stopPropagation();
|
3461
|
+
this.clear();
|
3462
|
+
}, this));
|
3463
|
+
|
3464
|
+
this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear));
|
3465
|
+
}
|
3466
|
+
*/
|
3467
|
+
},
|
3468
|
+
|
3469
|
+
value2html: function(value, element) {
|
3470
|
+
var text = value ? value.format(this.options.viewformat) : '';
|
3471
|
+
$(element).text(text);
|
3472
|
+
},
|
3473
|
+
|
3474
|
+
html2value: function(html) {
|
3475
|
+
return html ? moment(html, this.options.viewformat) : null;
|
3476
|
+
},
|
3477
|
+
|
3478
|
+
value2str: function(value) {
|
3479
|
+
return value ? value.format(this.options.format) : '';
|
3480
|
+
},
|
3481
|
+
|
3482
|
+
str2value: function(str) {
|
3483
|
+
return str ? moment(str, this.options.format) : null;
|
3484
|
+
},
|
3485
|
+
|
3486
|
+
value2submit: function(value) {
|
3487
|
+
return this.value2str(value);
|
3488
|
+
},
|
3489
|
+
|
3490
|
+
value2input: function(value) {
|
3491
|
+
this.$input.combodate('setValue', value);
|
3492
|
+
},
|
3493
|
+
|
3494
|
+
input2value: function() {
|
3495
|
+
return this.$input.combodate('getValue', null);
|
3496
|
+
},
|
3497
|
+
|
3498
|
+
activate: function() {
|
3499
|
+
this.$input.siblings('.combodate').find('select').eq(0).focus();
|
3500
|
+
},
|
3501
|
+
|
3502
|
+
/*
|
3503
|
+
clear: function() {
|
3504
|
+
this.$input.data('datepicker').date = null;
|
3505
|
+
this.$input.find('.active').removeClass('active');
|
3506
|
+
},
|
3507
|
+
*/
|
3508
|
+
|
3509
|
+
autosubmit: function() {
|
3510
|
+
|
3511
|
+
}
|
3512
|
+
|
3513
|
+
});
|
3514
|
+
|
3515
|
+
Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
3516
|
+
/**
|
3517
|
+
@property tpl
|
3518
|
+
@default <input type="text">
|
3519
|
+
**/
|
3520
|
+
tpl:'<input type="text">',
|
3521
|
+
/**
|
3522
|
+
@property inputclass
|
3523
|
+
@default null
|
3524
|
+
**/
|
3525
|
+
inputclass: null,
|
3526
|
+
/**
|
3527
|
+
Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
|
3528
|
+
See list of tokens in [momentjs docs](http://momentjs.com/docs/#/parsing/string-format)
|
3529
|
+
|
3530
|
+
@property format
|
3531
|
+
@type string
|
3532
|
+
@default YYYY-MM-DD
|
3533
|
+
**/
|
3534
|
+
format:'YYYY-MM-DD',
|
3535
|
+
/**
|
3536
|
+
Format used for displaying date. Also applied when converting date from element's text on init.
|
3537
|
+
If not specified equals to `format`.
|
3538
|
+
|
3539
|
+
@property viewformat
|
3540
|
+
@type string
|
3541
|
+
@default null
|
3542
|
+
**/
|
3543
|
+
viewformat: null,
|
3544
|
+
/**
|
3545
|
+
Template used for displaying dropdowns.
|
3546
|
+
|
3547
|
+
@property template
|
3548
|
+
@type string
|
3549
|
+
@default D / MMM / YYYY
|
3550
|
+
**/
|
3551
|
+
template: 'D / MMM / YYYY',
|
3552
|
+
/**
|
3553
|
+
Configuration of combodate.
|
3554
|
+
Full list of options: http://vitalets.github.com/combodate/#docs
|
3555
|
+
|
3556
|
+
@property combodate
|
3557
|
+
@type object
|
3558
|
+
@default null
|
3559
|
+
**/
|
3560
|
+
combodate: null
|
3561
|
+
|
3562
|
+
/*
|
3563
|
+
(not implemented yet)
|
3564
|
+
Text shown as clear date button.
|
3565
|
+
If <code>false</code> clear button will not be rendered.
|
3566
|
+
|
3567
|
+
@property clear
|
3568
|
+
@type boolean|string
|
3569
|
+
@default 'x clear'
|
3570
|
+
*/
|
3571
|
+
//clear: '× clear'
|
3572
|
+
});
|
3573
|
+
|
3574
|
+
$.fn.editabletypes.combodate = Constructor;
|
3575
|
+
|
3576
|
+
}(window.jQuery));
|
3577
|
+
|
2640
3578
|
/*
|
2641
3579
|
Editableform based on Twitter Bootstrap
|
2642
3580
|
*/
|
@@ -2666,7 +3604,7 @@ Editableform based on Twitter Bootstrap
|
|
2666
3604
|
(function ($) {
|
2667
3605
|
|
2668
3606
|
//extend methods
|
2669
|
-
$.extend($.fn.editableContainer.
|
3607
|
+
$.extend($.fn.editableContainer.Popup.prototype, {
|
2670
3608
|
containerName: 'popover',
|
2671
3609
|
//for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content)
|
2672
3610
|
innerCss: $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content',
|
@@ -2675,10 +3613,39 @@ Editableform based on Twitter Bootstrap
|
|
2675
3613
|
$.extend(this.containerOptions, {
|
2676
3614
|
trigger: 'manual',
|
2677
3615
|
selector: false,
|
2678
|
-
content: ' '
|
3616
|
+
content: ' ',
|
3617
|
+
template: $.fn.popover.defaults.template
|
2679
3618
|
});
|
3619
|
+
|
3620
|
+
//as template property is used in inputs, hide it from popover
|
3621
|
+
var t;
|
3622
|
+
if(this.$element.data('template')) {
|
3623
|
+
t = this.$element.data('template');
|
3624
|
+
this.$element.removeData('template');
|
3625
|
+
}
|
3626
|
+
|
2680
3627
|
this.call(this.containerOptions);
|
2681
|
-
|
3628
|
+
|
3629
|
+
if(t) {
|
3630
|
+
//restore data('template')
|
3631
|
+
this.$element.data('template', t);
|
3632
|
+
}
|
3633
|
+
},
|
3634
|
+
|
3635
|
+
/* show */
|
3636
|
+
innerShow: function () {
|
3637
|
+
this.call('show');
|
3638
|
+
},
|
3639
|
+
|
3640
|
+
/* hide */
|
3641
|
+
innerHide: function () {
|
3642
|
+
this.call('hide');
|
3643
|
+
},
|
3644
|
+
|
3645
|
+
/* destroy */
|
3646
|
+
innerDestroy: function() {
|
3647
|
+
this.call('destroy');
|
3648
|
+
},
|
2682
3649
|
|
2683
3650
|
setContainerOption: function(key, value) {
|
2684
3651
|
this.container().options[key] = value;
|
@@ -2742,18 +3709,13 @@ Editableform based on Twitter Bootstrap
|
|
2742
3709
|
}
|
2743
3710
|
});
|
2744
3711
|
|
2745
|
-
//defaults
|
2746
|
-
/*
|
2747
|
-
$.fn.editableContainer.defaults = $.extend({}, $.fn.popover.defaults, $.fn.editableContainer.defaults, {
|
2748
|
-
|
2749
|
-
});
|
2750
|
-
*/
|
2751
|
-
|
2752
3712
|
}(window.jQuery));
|
2753
3713
|
/**
|
2754
3714
|
Bootstrap-datepicker.
|
2755
|
-
Description and examples:
|
2756
|
-
For
|
3715
|
+
Description and examples: https://github.com/eternicode/bootstrap-datepicker.
|
3716
|
+
For **i18n** you should include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales
|
3717
|
+
and set `language` option.
|
3718
|
+
Since 1.4.0 date has different appearance in **popup** and **inline** modes.
|
2757
3719
|
|
2758
3720
|
@class date
|
2759
3721
|
@extends abstractinput
|
@@ -2777,45 +3739,52 @@ $(function(){
|
|
2777
3739
|
|
2778
3740
|
var Date = function (options) {
|
2779
3741
|
this.init('date', options, Date.defaults);
|
2780
|
-
|
2781
|
-
//set popular options directly from settings or data-* attributes
|
2782
|
-
var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']);
|
2783
|
-
|
2784
|
-
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
2785
|
-
this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker);
|
2786
|
-
|
2787
|
-
//by default viewformat equals to format
|
2788
|
-
if(!this.options.viewformat) {
|
2789
|
-
this.options.viewformat = this.options.datepicker.format;
|
2790
|
-
}
|
2791
|
-
|
2792
|
-
//language
|
2793
|
-
this.options.datepicker.language = this.options.datepicker.language || 'en';
|
2794
|
-
|
2795
|
-
//store DPglobal
|
2796
|
-
this.dpg = $.fn.datepicker.DPGlobal;
|
2797
|
-
|
2798
|
-
//store parsed formats
|
2799
|
-
this.parsedFormat = this.dpg.parseFormat(this.options.datepicker.format);
|
2800
|
-
this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat);
|
3742
|
+
this.initPicker(options, Date.defaults);
|
2801
3743
|
};
|
2802
3744
|
|
2803
3745
|
$.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput);
|
2804
3746
|
|
2805
3747
|
$.extend(Date.prototype, {
|
3748
|
+
initPicker: function(options, defaults) {
|
3749
|
+
//'format' is set directly from settings or data-* attributes
|
3750
|
+
|
3751
|
+
//by default viewformat equals to format
|
3752
|
+
if(!this.options.viewformat) {
|
3753
|
+
this.options.viewformat = this.options.format;
|
3754
|
+
}
|
3755
|
+
|
3756
|
+
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
3757
|
+
//since 1.4 datepicker internally uses viewformat instead of format. Format is for submit only
|
3758
|
+
this.options.datepicker = $.extend({}, defaults.datepicker, options.datepicker, {
|
3759
|
+
format: this.options.viewformat
|
3760
|
+
});
|
3761
|
+
|
3762
|
+
//language
|
3763
|
+
this.options.datepicker.language = this.options.datepicker.language || 'en';
|
3764
|
+
|
3765
|
+
//store DPglobal
|
3766
|
+
this.dpg = $.fn.datepicker.DPGlobal;
|
3767
|
+
|
3768
|
+
//store parsed formats
|
3769
|
+
this.parsedFormat = this.dpg.parseFormat(this.options.format);
|
3770
|
+
this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat);
|
3771
|
+
},
|
3772
|
+
|
2806
3773
|
render: function () {
|
2807
|
-
Date.superclass.render.call(this);
|
2808
3774
|
this.$input.datepicker(this.options.datepicker);
|
2809
|
-
|
3775
|
+
|
3776
|
+
//"clear" link
|
2810
3777
|
if(this.options.clear) {
|
2811
3778
|
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
|
2812
3779
|
e.preventDefault();
|
2813
3780
|
e.stopPropagation();
|
2814
3781
|
this.clear();
|
2815
3782
|
}, this));
|
2816
|
-
|
3783
|
+
|
3784
|
+
this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear));
|
3785
|
+
}
|
2817
3786
|
},
|
2818
|
-
|
3787
|
+
|
2819
3788
|
value2html: function(value, element) {
|
2820
3789
|
var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : '';
|
2821
3790
|
Date.superclass.value2html(text, element);
|
@@ -2869,12 +3838,12 @@ $(function(){
|
|
2869
3838
|
@property tpl
|
2870
3839
|
@default <div></div>
|
2871
3840
|
**/
|
2872
|
-
tpl:'<div></div>',
|
3841
|
+
tpl:'<div class="editable-date well"></div>',
|
2873
3842
|
/**
|
2874
3843
|
@property inputclass
|
2875
|
-
@default
|
3844
|
+
@default null
|
2876
3845
|
**/
|
2877
|
-
inputclass:
|
3846
|
+
inputclass: null,
|
2878
3847
|
/**
|
2879
3848
|
Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
|
2880
3849
|
Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code>
|
@@ -2925,6 +3894,84 @@ $(function(){
|
|
2925
3894
|
|
2926
3895
|
}(window.jQuery));
|
2927
3896
|
|
3897
|
+
/**
|
3898
|
+
Bootstrap datefield input - modification for inline mode.
|
3899
|
+
Shows normal <input type="text"> and binds popup datepicker.
|
3900
|
+
Automatically shown in inline mode.
|
3901
|
+
|
3902
|
+
@class datefield
|
3903
|
+
@extends date
|
3904
|
+
|
3905
|
+
@since 1.4.0
|
3906
|
+
**/
|
3907
|
+
(function ($) {
|
3908
|
+
|
3909
|
+
var DateField = function (options) {
|
3910
|
+
this.init('datefield', options, DateField.defaults);
|
3911
|
+
this.initPicker(options, DateField.defaults);
|
3912
|
+
};
|
3913
|
+
|
3914
|
+
$.fn.editableutils.inherit(DateField, $.fn.editabletypes.date);
|
3915
|
+
|
3916
|
+
$.extend(DateField.prototype, {
|
3917
|
+
render: function () {
|
3918
|
+
this.$input = this.$tpl.find('input');
|
3919
|
+
this.setClass();
|
3920
|
+
this.setAttr('placeholder');
|
3921
|
+
|
3922
|
+
this.$tpl.datepicker(this.options.datepicker);
|
3923
|
+
|
3924
|
+
//need to disable original event handlers
|
3925
|
+
this.$input.off('focus keydown');
|
3926
|
+
|
3927
|
+
//update value of datepicker
|
3928
|
+
this.$input.keyup($.proxy(function(){
|
3929
|
+
this.$tpl.removeData('date');
|
3930
|
+
this.$tpl.datepicker('update');
|
3931
|
+
}, this));
|
3932
|
+
|
3933
|
+
},
|
3934
|
+
|
3935
|
+
value2input: function(value) {
|
3936
|
+
this.$input.val(value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : '');
|
3937
|
+
this.$tpl.datepicker('update');
|
3938
|
+
},
|
3939
|
+
|
3940
|
+
input2value: function() {
|
3941
|
+
return this.html2value(this.$input.val());
|
3942
|
+
},
|
3943
|
+
|
3944
|
+
activate: function() {
|
3945
|
+
$.fn.editabletypes.text.prototype.activate.call(this);
|
3946
|
+
},
|
3947
|
+
|
3948
|
+
autosubmit: function() {
|
3949
|
+
//reset autosubmit to empty
|
3950
|
+
}
|
3951
|
+
});
|
3952
|
+
|
3953
|
+
DateField.defaults = $.extend({}, $.fn.editabletypes.date.defaults, {
|
3954
|
+
/**
|
3955
|
+
@property tpl
|
3956
|
+
**/
|
3957
|
+
tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',
|
3958
|
+
/**
|
3959
|
+
@property inputclass
|
3960
|
+
@default 'input-small'
|
3961
|
+
**/
|
3962
|
+
inputclass: 'input-small',
|
3963
|
+
|
3964
|
+
/* datepicker config */
|
3965
|
+
datepicker: {
|
3966
|
+
weekStart: 0,
|
3967
|
+
startView: 0,
|
3968
|
+
autoclose: true
|
3969
|
+
}
|
3970
|
+
});
|
3971
|
+
|
3972
|
+
$.fn.editabletypes.datefield = DateField;
|
3973
|
+
|
3974
|
+
}(window.jQuery));
|
2928
3975
|
/* =========================================================
|
2929
3976
|
* bootstrap-datepicker.js
|
2930
3977
|
* http://www.eyecon.ro/bootstrap-datepicker
|
@@ -2963,51 +4010,45 @@ $(function(){
|
|
2963
4010
|
this.element = $(element);
|
2964
4011
|
this.language = options.language||this.element.data('date-language')||"en";
|
2965
4012
|
this.language = this.language in dates ? this.language : "en";
|
4013
|
+
this.isRTL = dates[this.language].rtl||false;
|
2966
4014
|
this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
|
2967
|
-
|
4015
|
+
this.isInline = false;
|
2968
4016
|
this.isInput = this.element.is('input');
|
2969
4017
|
this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
|
2970
4018
|
this.hasInput = this.component && this.element.find('input').length;
|
2971
4019
|
if(this.component && this.component.length === 0)
|
2972
4020
|
this.component = false;
|
2973
4021
|
|
2974
|
-
|
2975
|
-
this.element.on({
|
2976
|
-
focus: $.proxy(this.show, this),
|
2977
|
-
keyup: $.proxy(this.update, this),
|
2978
|
-
keydown: $.proxy(this.keydown, this)
|
2979
|
-
});
|
2980
|
-
} else if(this.component && this.hasInput) { //component: input + button
|
2981
|
-
// For components that are not readonly, allow keyboard nav
|
2982
|
-
this.element.find('input').on({
|
2983
|
-
focus: $.proxy(this.show, this),
|
2984
|
-
keyup: $.proxy(this.update, this),
|
2985
|
-
keydown: $.proxy(this.keydown, this)
|
2986
|
-
});
|
2987
|
-
|
2988
|
-
this.component.on('click', $.proxy(this.show, this));
|
2989
|
-
} else if(this.element.is('div')) { //inline datepicker
|
2990
|
-
this.isInline = true;
|
2991
|
-
} else {
|
2992
|
-
this.element.on('click', $.proxy(this.show, this));
|
2993
|
-
}
|
2994
|
-
|
2995
|
-
this.picker = $(DPGlobal.template)
|
2996
|
-
.appendTo(this.isInline ? this.element : 'body')
|
2997
|
-
.on({
|
2998
|
-
click: $.proxy(this.click, this),
|
2999
|
-
mousedown: $.proxy(this.mousedown, this)
|
3000
|
-
});
|
3001
|
-
|
3002
|
-
if(this.isInline) {
|
3003
|
-
this.picker.addClass('datepicker-inline');
|
3004
|
-
} else {
|
3005
|
-
this.picker.addClass('dropdown-menu');
|
3006
|
-
}
|
4022
|
+
this._attachEvents();
|
3007
4023
|
|
4024
|
+
this.forceParse = true;
|
4025
|
+
if ('forceParse' in options) {
|
4026
|
+
this.forceParse = options.forceParse;
|
4027
|
+
} else if ('dateForceParse' in this.element.data()) {
|
4028
|
+
this.forceParse = this.element.data('date-force-parse');
|
4029
|
+
}
|
4030
|
+
|
4031
|
+
|
4032
|
+
this.picker = $(DPGlobal.template)
|
4033
|
+
.appendTo(this.isInline ? this.element : 'body')
|
4034
|
+
.on({
|
4035
|
+
click: $.proxy(this.click, this),
|
4036
|
+
mousedown: $.proxy(this.mousedown, this)
|
4037
|
+
});
|
4038
|
+
|
4039
|
+
if(this.isInline) {
|
4040
|
+
this.picker.addClass('datepicker-inline');
|
4041
|
+
} else {
|
4042
|
+
this.picker.addClass('datepicker-dropdown dropdown-menu');
|
4043
|
+
}
|
4044
|
+
if (this.isRTL){
|
4045
|
+
this.picker.addClass('datepicker-rtl');
|
4046
|
+
this.picker.find('.prev i, .next i')
|
4047
|
+
.toggleClass('icon-arrow-left icon-arrow-right');
|
4048
|
+
}
|
3008
4049
|
$(document).on('mousedown', function (e) {
|
3009
4050
|
// Clicked outside the datepicker, hide it
|
3010
|
-
if ($(e.target).closest('.datepicker').length
|
4051
|
+
if ($(e.target).closest('.datepicker').length === 0) {
|
3011
4052
|
that.hide();
|
3012
4053
|
}
|
3013
4054
|
});
|
@@ -3026,6 +4067,7 @@ $(function(){
|
|
3026
4067
|
this.keyboardNavigation = this.element.data('date-keyboard-navigation');
|
3027
4068
|
}
|
3028
4069
|
|
4070
|
+
this.viewMode = this.startViewMode = 0;
|
3029
4071
|
switch(options.startView || this.element.data('date-start-view')){
|
3030
4072
|
case 2:
|
3031
4073
|
case 'decade':
|
@@ -3035,11 +4077,6 @@ $(function(){
|
|
3035
4077
|
case 'year':
|
3036
4078
|
this.viewMode = this.startViewMode = 1;
|
3037
4079
|
break;
|
3038
|
-
case 0:
|
3039
|
-
case 'month':
|
3040
|
-
default:
|
3041
|
-
this.viewMode = this.startViewMode = 0;
|
3042
|
-
break;
|
3043
4080
|
}
|
3044
4081
|
|
3045
4082
|
this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
|
@@ -3049,21 +4086,73 @@ $(function(){
|
|
3049
4086
|
this.weekEnd = ((this.weekStart + 6) % 7);
|
3050
4087
|
this.startDate = -Infinity;
|
3051
4088
|
this.endDate = Infinity;
|
4089
|
+
this.daysOfWeekDisabled = [];
|
3052
4090
|
this.setStartDate(options.startDate||this.element.data('date-startdate'));
|
3053
4091
|
this.setEndDate(options.endDate||this.element.data('date-enddate'));
|
4092
|
+
this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled'));
|
3054
4093
|
this.fillDow();
|
3055
4094
|
this.fillMonths();
|
3056
4095
|
this.update();
|
3057
4096
|
this.showMode();
|
3058
4097
|
|
3059
|
-
|
3060
|
-
|
3061
|
-
|
4098
|
+
if(this.isInline) {
|
4099
|
+
this.show();
|
4100
|
+
}
|
3062
4101
|
};
|
3063
4102
|
|
3064
4103
|
Datepicker.prototype = {
|
3065
4104
|
constructor: Datepicker,
|
3066
4105
|
|
4106
|
+
_events: [],
|
4107
|
+
_attachEvents: function(){
|
4108
|
+
this._detachEvents();
|
4109
|
+
if (this.isInput) { // single input
|
4110
|
+
this._events = [
|
4111
|
+
[this.element, {
|
4112
|
+
focus: $.proxy(this.show, this),
|
4113
|
+
keyup: $.proxy(this.update, this),
|
4114
|
+
keydown: $.proxy(this.keydown, this)
|
4115
|
+
}]
|
4116
|
+
];
|
4117
|
+
}
|
4118
|
+
else if (this.component && this.hasInput){ // component: input + button
|
4119
|
+
this._events = [
|
4120
|
+
// For components that are not readonly, allow keyboard nav
|
4121
|
+
[this.element.find('input'), {
|
4122
|
+
focus: $.proxy(this.show, this),
|
4123
|
+
keyup: $.proxy(this.update, this),
|
4124
|
+
keydown: $.proxy(this.keydown, this)
|
4125
|
+
}],
|
4126
|
+
[this.component, {
|
4127
|
+
click: $.proxy(this.show, this)
|
4128
|
+
}]
|
4129
|
+
];
|
4130
|
+
}
|
4131
|
+
else if (this.element.is('div')) { // inline datepicker
|
4132
|
+
this.isInline = true;
|
4133
|
+
}
|
4134
|
+
else {
|
4135
|
+
this._events = [
|
4136
|
+
[this.element, {
|
4137
|
+
click: $.proxy(this.show, this)
|
4138
|
+
}]
|
4139
|
+
];
|
4140
|
+
}
|
4141
|
+
for (var i=0, el, ev; i<this._events.length; i++){
|
4142
|
+
el = this._events[i][0];
|
4143
|
+
ev = this._events[i][1];
|
4144
|
+
el.on(ev);
|
4145
|
+
}
|
4146
|
+
},
|
4147
|
+
_detachEvents: function(){
|
4148
|
+
for (var i=0, el, ev; i<this._events.length; i++){
|
4149
|
+
el = this._events[i][0];
|
4150
|
+
ev = this._events[i][1];
|
4151
|
+
el.off(ev);
|
4152
|
+
}
|
4153
|
+
this._events = [];
|
4154
|
+
},
|
4155
|
+
|
3067
4156
|
show: function(e) {
|
3068
4157
|
this.picker.show();
|
3069
4158
|
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
|
@@ -3081,7 +4170,7 @@ $(function(){
|
|
3081
4170
|
},
|
3082
4171
|
|
3083
4172
|
hide: function(e){
|
3084
|
-
|
4173
|
+
if(this.isInline) return;
|
3085
4174
|
this.picker.hide();
|
3086
4175
|
$(window).off('resize', this.place);
|
3087
4176
|
this.viewMode = this.startViewMode;
|
@@ -3089,7 +4178,14 @@ $(function(){
|
|
3089
4178
|
if (!this.isInput) {
|
3090
4179
|
$(document).off('mousedown', this.hide);
|
3091
4180
|
}
|
3092
|
-
|
4181
|
+
|
4182
|
+
if (
|
4183
|
+
this.forceParse &&
|
4184
|
+
(
|
4185
|
+
this.isInput && this.element.val() ||
|
4186
|
+
this.hasInput && this.element.find('input').val()
|
4187
|
+
)
|
4188
|
+
)
|
3093
4189
|
this.setValue();
|
3094
4190
|
this.element.trigger({
|
3095
4191
|
type: 'hide',
|
@@ -3097,9 +4193,15 @@ $(function(){
|
|
3097
4193
|
});
|
3098
4194
|
},
|
3099
4195
|
|
4196
|
+
remove: function() {
|
4197
|
+
this._detachEvents();
|
4198
|
+
this.picker.remove();
|
4199
|
+
delete this.element.data().datepicker;
|
4200
|
+
},
|
4201
|
+
|
3100
4202
|
getDate: function() {
|
3101
4203
|
var d = this.getUTCDate();
|
3102
|
-
return new Date(d.getTime() + (d.getTimezoneOffset()*60000))
|
4204
|
+
return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
|
3103
4205
|
},
|
3104
4206
|
|
3105
4207
|
getUTCDate: function() {
|
@@ -3119,18 +4221,19 @@ $(function(){
|
|
3119
4221
|
var formatted = this.getFormattedDate();
|
3120
4222
|
if (!this.isInput) {
|
3121
4223
|
if (this.component){
|
3122
|
-
this.element.find('input').
|
4224
|
+
this.element.find('input').val(formatted);
|
3123
4225
|
}
|
3124
4226
|
this.element.data('date', formatted);
|
3125
4227
|
} else {
|
3126
|
-
this.element.
|
4228
|
+
this.element.val(formatted);
|
3127
4229
|
}
|
3128
4230
|
},
|
3129
4231
|
|
3130
|
-
|
3131
|
-
|
3132
|
-
|
3133
|
-
|
4232
|
+
getFormattedDate: function(format) {
|
4233
|
+
if (format === undefined)
|
4234
|
+
format = this.format;
|
4235
|
+
return DPGlobal.formatDate(this.date, format, this.language);
|
4236
|
+
},
|
3134
4237
|
|
3135
4238
|
setStartDate: function(startDate){
|
3136
4239
|
this.startDate = startDate||-Infinity;
|
@@ -3150,32 +4253,46 @@ $(function(){
|
|
3150
4253
|
this.updateNavArrows();
|
3151
4254
|
},
|
3152
4255
|
|
4256
|
+
setDaysOfWeekDisabled: function(daysOfWeekDisabled){
|
4257
|
+
this.daysOfWeekDisabled = daysOfWeekDisabled||[];
|
4258
|
+
if (!$.isArray(this.daysOfWeekDisabled)) {
|
4259
|
+
this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
|
4260
|
+
}
|
4261
|
+
this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
|
4262
|
+
return parseInt(d, 10);
|
4263
|
+
});
|
4264
|
+
this.update();
|
4265
|
+
this.updateNavArrows();
|
4266
|
+
},
|
4267
|
+
|
3153
4268
|
place: function(){
|
3154
|
-
|
4269
|
+
if(this.isInline) return;
|
3155
4270
|
var zIndex = parseInt(this.element.parents().filter(function() {
|
3156
4271
|
return $(this).css('z-index') != 'auto';
|
3157
4272
|
}).first().css('z-index'))+10;
|
3158
4273
|
var offset = this.component ? this.component.offset() : this.element.offset();
|
4274
|
+
var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true);
|
3159
4275
|
this.picker.css({
|
3160
|
-
top: offset.top +
|
4276
|
+
top: offset.top + height,
|
3161
4277
|
left: offset.left,
|
3162
4278
|
zIndex: zIndex
|
3163
4279
|
});
|
3164
4280
|
},
|
3165
4281
|
|
3166
4282
|
update: function(){
|
3167
|
-
|
3168
|
-
|
3169
|
-
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3173
|
-
|
4283
|
+
var date, fromArgs = false;
|
4284
|
+
if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
|
4285
|
+
date = arguments[0];
|
4286
|
+
fromArgs = true;
|
4287
|
+
} else {
|
4288
|
+
date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
|
4289
|
+
}
|
3174
4290
|
|
3175
4291
|
this.date = DPGlobal.parseDate(date, this.format, this.language);
|
3176
4292
|
|
3177
|
-
|
4293
|
+
if(fromArgs) this.setValue();
|
3178
4294
|
|
4295
|
+
var oldViewDate = this.viewDate;
|
3179
4296
|
if (this.date < this.startDate) {
|
3180
4297
|
this.viewDate = new Date(this.startDate);
|
3181
4298
|
} else if (this.date > this.endDate) {
|
@@ -3183,12 +4300,19 @@ $(function(){
|
|
3183
4300
|
} else {
|
3184
4301
|
this.viewDate = new Date(this.date);
|
3185
4302
|
}
|
4303
|
+
|
4304
|
+
if (oldViewDate && oldViewDate.getTime() != this.viewDate.getTime()){
|
4305
|
+
this.element.trigger({
|
4306
|
+
type: 'changeDate',
|
4307
|
+
date: this.viewDate
|
4308
|
+
});
|
4309
|
+
}
|
3186
4310
|
this.fill();
|
3187
4311
|
},
|
3188
4312
|
|
3189
4313
|
fillDow: function(){
|
3190
|
-
var dowCnt = this.weekStart
|
3191
|
-
|
4314
|
+
var dowCnt = this.weekStart,
|
4315
|
+
html = '<tr>';
|
3192
4316
|
while (dowCnt < this.weekStart + 7) {
|
3193
4317
|
html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
|
3194
4318
|
}
|
@@ -3197,8 +4321,8 @@ $(function(){
|
|
3197
4321
|
},
|
3198
4322
|
|
3199
4323
|
fillMonths: function(){
|
3200
|
-
var html = ''
|
3201
|
-
|
4324
|
+
var html = '',
|
4325
|
+
i = 0;
|
3202
4326
|
while (i < 12) {
|
3203
4327
|
html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
|
3204
4328
|
}
|
@@ -3251,7 +4375,8 @@ $(function(){
|
|
3251
4375
|
if (currentDate && prevMonth.valueOf() == currentDate) {
|
3252
4376
|
clsName += ' active';
|
3253
4377
|
}
|
3254
|
-
if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate
|
4378
|
+
if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
|
4379
|
+
$.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
|
3255
4380
|
clsName += ' disabled';
|
3256
4381
|
}
|
3257
4382
|
html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
|
@@ -3392,7 +4517,7 @@ $(function(){
|
|
3392
4517
|
var year = this.viewDate.getUTCFullYear(),
|
3393
4518
|
month = this.viewDate.getUTCMonth();
|
3394
4519
|
if (target.is('.old')) {
|
3395
|
-
if (month
|
4520
|
+
if (month === 0) {
|
3396
4521
|
month = 11;
|
3397
4522
|
year -= 1;
|
3398
4523
|
} else {
|
@@ -3432,8 +4557,8 @@ $(function(){
|
|
3432
4557
|
}
|
3433
4558
|
if (element) {
|
3434
4559
|
element.change();
|
3435
|
-
if (this.autoclose) {
|
3436
|
-
|
4560
|
+
if (this.autoclose && (!which || which == 'date')) {
|
4561
|
+
this.hide();
|
3437
4562
|
}
|
3438
4563
|
}
|
3439
4564
|
},
|
@@ -3579,16 +4704,16 @@ $(function(){
|
|
3579
4704
|
if (dir) {
|
3580
4705
|
this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
|
3581
4706
|
}
|
3582
|
-
|
3583
|
-
|
3584
|
-
|
3585
|
-
|
3586
|
-
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3590
|
-
|
3591
|
-
|
4707
|
+
/*
|
4708
|
+
vitalets: fixing bug of very special conditions:
|
4709
|
+
jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
|
4710
|
+
Method show() does not set display css correctly and datepicker is not shown.
|
4711
|
+
Changed to .css('display', 'block') solve the problem.
|
4712
|
+
See https://github.com/vitalets/x-editable/issues/37
|
4713
|
+
|
4714
|
+
In jquery 1.7.2+ everything works fine.
|
4715
|
+
*/
|
4716
|
+
//this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
3592
4717
|
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
|
3593
4718
|
this.updateNavArrows();
|
3594
4719
|
}
|
@@ -3622,7 +4747,7 @@ $(function(){
|
|
3622
4747
|
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
3623
4748
|
today: "Today"
|
3624
4749
|
}
|
3625
|
-
}
|
4750
|
+
};
|
3626
4751
|
|
3627
4752
|
var DPGlobal = {
|
3628
4753
|
modes: [
|
@@ -3642,28 +4767,28 @@ $(function(){
|
|
3642
4767
|
navStep: 10
|
3643
4768
|
}],
|
3644
4769
|
isLeapYear: function (year) {
|
3645
|
-
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
|
4770
|
+
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
|
3646
4771
|
},
|
3647
4772
|
getDaysInMonth: function (year, month) {
|
3648
|
-
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
|
4773
|
+
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
|
3649
4774
|
},
|
3650
|
-
validParts: /dd?|mm?|MM?|yy(?:yy)?/g,
|
3651
|
-
nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g,
|
4775
|
+
validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
|
4776
|
+
nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
|
3652
4777
|
parseFormat: function(format){
|
3653
4778
|
// IE treats \0 as a string end in inputs (truncating the value),
|
3654
4779
|
// so it's a bad format delimiter, anyway
|
3655
4780
|
var separators = format.replace(this.validParts, '\0').split('\0'),
|
3656
4781
|
parts = format.match(this.validParts);
|
3657
|
-
if (!separators || !separators.length || !parts || parts.length
|
4782
|
+
if (!separators || !separators.length || !parts || parts.length === 0){
|
3658
4783
|
throw new Error("Invalid date format.");
|
3659
4784
|
}
|
3660
4785
|
return {separators: separators, parts: parts};
|
3661
4786
|
},
|
3662
4787
|
parseDate: function(date, format, language) {
|
3663
4788
|
if (date instanceof Date) return date;
|
3664
|
-
if (/^[
|
3665
|
-
var part_re = /([
|
3666
|
-
parts = date.match(/([
|
4789
|
+
if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) {
|
4790
|
+
var part_re = /([\-+]\d+)([dmwy])/,
|
4791
|
+
parts = date.match(/([\-+]\d+)([dmwy])/g),
|
3667
4792
|
part, dir;
|
3668
4793
|
date = new Date();
|
3669
4794
|
for (var i=0; i<parts.length; i++) {
|
@@ -3708,10 +4833,18 @@ $(function(){
|
|
3708
4833
|
setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
|
3709
4834
|
setters_map['dd'] = setters_map['d'];
|
3710
4835
|
date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
|
3711
|
-
|
3712
|
-
|
4836
|
+
var fparts = format.parts.slice();
|
4837
|
+
// Remove noop parts
|
4838
|
+
if (parts.length != fparts.length) {
|
4839
|
+
fparts = $(fparts).filter(function(i,p){
|
4840
|
+
return $.inArray(p, setters_order) !== -1;
|
4841
|
+
}).toArray();
|
4842
|
+
}
|
4843
|
+
// Process remainder
|
4844
|
+
if (parts.length == fparts.length) {
|
4845
|
+
for (var i=0, cnt = fparts.length; i < cnt; i++) {
|
3713
4846
|
val = parseInt(parts[i], 10);
|
3714
|
-
part =
|
4847
|
+
part = fparts[i];
|
3715
4848
|
if (isNaN(val)) {
|
3716
4849
|
switch(part) {
|
3717
4850
|
case 'MM':
|
@@ -3736,8 +4869,8 @@ $(function(){
|
|
3736
4869
|
}
|
3737
4870
|
for (var i=0, s; i<setters_order.length; i++){
|
3738
4871
|
s = setters_order[i];
|
3739
|
-
if (s in parsed)
|
3740
|
-
setters_map[s](date, parsed[s])
|
4872
|
+
if (s in parsed && !isNaN(parsed[s]))
|
4873
|
+
setters_map[s](date, parsed[s]);
|
3741
4874
|
}
|
3742
4875
|
}
|
3743
4876
|
return date;
|
@@ -3745,6 +4878,8 @@ $(function(){
|
|
3745
4878
|
formatDate: function(date, format, language){
|
3746
4879
|
var val = {
|
3747
4880
|
d: date.getUTCDate(),
|
4881
|
+
D: dates[language].daysShort[date.getUTCDay()],
|
4882
|
+
DD: dates[language].days[date.getUTCDay()],
|
3748
4883
|
m: date.getUTCMonth() + 1,
|
3749
4884
|
M: dates[language].monthsShort[date.getUTCMonth()],
|
3750
4885
|
MM: dates[language].months[date.getUTCMonth()],
|
@@ -3757,7 +4892,7 @@ $(function(){
|
|
3757
4892
|
seps = $.extend([], format.separators);
|
3758
4893
|
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
3759
4894
|
if (seps.length)
|
3760
|
-
date.push(seps.shift())
|
4895
|
+
date.push(seps.shift());
|
3761
4896
|
date.push(val[format.parts[i]]);
|
3762
4897
|
}
|
3763
4898
|
return date.join('');
|
@@ -3795,7 +4930,7 @@ $(function(){
|
|
3795
4930
|
'</table>'+
|
3796
4931
|
'</div>'+
|
3797
4932
|
'</div>';
|
3798
|
-
|
3799
|
-
|
3800
|
-
|
4933
|
+
|
4934
|
+
$.fn.datepicker.DPGlobal = DPGlobal;
|
4935
|
+
|
3801
4936
|
}( window.jQuery );
|