bootstrap-x-editable-rails 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # X-editable 1.4.3 for Rails
1
+ # X-editable for Rails [![Gem Version](https://badge.fury.io/rb/bootstrap-x-editable-rails.png)](http://badge.fury.io/rb/bootstrap-x-editable-rails)
2
2
 
3
3
  [X-editable](https://github.com/vitalets/x-editable) is an in-place editing plugin with support for Twitter Bootstrap, jQuery UI or pure jQuery.
4
4
 
@@ -1,5 +1,5 @@
1
1
  module BootstrapXEditableRails
2
2
  module Rails
3
- VERSION = "1.4.3"
3
+ VERSION = "1.4.4"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- /*! X-editable - v1.4.3
1
+ /*! X-editable - v1.4.4
2
2
  * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
3
  * http://github.com/vitalets/x-editable
4
4
  * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
@@ -13,7 +13,8 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
13
13
  @uses textarea
14
14
  **/
15
15
  (function ($) {
16
-
16
+ "use strict";
17
+
17
18
  var EditableForm = function (div, options) {
18
19
  this.options = $.extend({}, $.fn.editableform.defaults, options);
19
20
  this.$div = $(div); //div, containing form. Not form tag. Not editable-element.
@@ -37,7 +38,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
37
38
  this.$form = $($.fn.editableform.template);
38
39
  },
39
40
  initButtons: function() {
40
- this.$form.find('.editable-buttons').append($.fn.editableform.buttons);
41
+ var $btn = this.$form.find('.editable-buttons');
42
+ $btn.append($.fn.editableform.buttons);
43
+ if(this.options.showbuttons === 'bottom') {
44
+ $btn.addClass('editable-buttons-bottom');
45
+ }
41
46
  },
42
47
  /**
43
48
  Renders editableform
@@ -257,8 +262,15 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
257
262
  this.$div.triggerHandler('save', {newValue: newValue, response: response});
258
263
  }, this))
259
264
  .fail($.proxy(function(xhr) {
260
- this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
261
- this.showForm();
265
+ var msg;
266
+ if(typeof this.options.error === 'function') {
267
+ msg = this.options.error.call(this.options.scope, xhr, newValue);
268
+ } else {
269
+ msg = typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!';
270
+ }
271
+
272
+ this.error(msg);
273
+ this.showForm();
262
274
  }, this));
263
275
  },
264
276
 
@@ -270,7 +282,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
270
282
  this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true);
271
283
 
272
284
  var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk,
273
- send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
285
+ send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk !== null && pk !== undefined)))),
274
286
  params;
275
287
 
276
288
  if (send) { //send to server
@@ -478,7 +490,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
478
490
  validate: null,
479
491
  /**
480
492
  Success callback. Called when value successfully sent on server and **response status = 200**.
481
- Useful to work with json response. For example, if your backend response can be <code>{success: true}</code>
493
+ Usefull to work with json response. For example, if your backend response can be <code>{success: true}</code>
482
494
  or <code>{success: false, msg: "server error"}</code> you can check it inside this callback.
483
495
  If it returns **string** - means error occured and string is shown as error message.
484
496
  If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user.
@@ -494,6 +506,25 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
494
506
  **/
495
507
  success: null,
496
508
  /**
509
+ Error callback. Called when request failed (response status != 200).
510
+ Usefull when you want to parse error response and display a custom message.
511
+ Must return **string** - the message to be displayed in the error block.
512
+
513
+ @property error
514
+ @type function
515
+ @default null
516
+ @since 1.4.4
517
+ @example
518
+ error: function(response, newValue) {
519
+ if(response.status === 500) {
520
+ return 'Service unavailable. Please try later.';
521
+ } else {
522
+ return response.responseText;
523
+ }
524
+ }
525
+ **/
526
+ error: null,
527
+ /**
497
528
  Additional options for submit ajax request.
498
529
  List of values: http://api.jquery.com/jQuery.ajax
499
530
 
@@ -509,11 +540,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
509
540
  **/
510
541
  ajaxOptions: null,
511
542
  /**
512
- Whether to show buttons or not.
543
+ Where to show buttons: left(true)|bottom|false
513
544
  Form without buttons is auto-submitted.
514
545
 
515
546
  @property showbuttons
516
- @type boolean
547
+ @type boolean|string
517
548
  @default true
518
549
  @since 1.1.1
519
550
  **/
@@ -537,7 +568,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
537
568
  @default false
538
569
  @since 1.2.0
539
570
  **/
540
- savenochange: false
571
+ savenochange: false
541
572
  };
542
573
 
543
574
  /*
@@ -564,10 +595,13 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
564
595
  //error class attached to editable-error-block
565
596
  $.fn.editableform.errorBlockClass = 'editable-error';
566
597
  }(window.jQuery));
598
+
567
599
  /**
568
600
  * EditableForm utilites
569
601
  */
570
602
  (function ($) {
603
+ "use strict";
604
+
571
605
  //utils
572
606
  $.fn.editableutils = {
573
607
  /**
@@ -761,6 +795,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
761
795
  type = 'combodate';
762
796
  }
763
797
  }
798
+
799
+ //`datetime` should be datetimefield in 'inline' mode
800
+ if(type === 'datetime' && options.mode === 'inline') {
801
+ type = 'datetimefield';
802
+ }
764
803
 
765
804
  //change wysihtml5 to textarea for jquery UI and plain versions
766
805
  if(type === 'wysihtml5' && !$.fn.editabletypes[type]) {
@@ -792,6 +831,7 @@ Applied as jQuery method.
792
831
  @uses editableform
793
832
  **/
794
833
  (function ($) {
834
+ "use strict";
795
835
 
796
836
  var Popup = function (element, options) {
797
837
  this.init(element, options);
@@ -805,6 +845,7 @@ Applied as jQuery method.
805
845
  Popup.prototype = {
806
846
  containerName: null, //tbd in child class
807
847
  innerCss: null, //tbd in child class
848
+ containerClass: 'editable-container editable-popup', //css class applied to container element
808
849
  init: function(element, options) {
809
850
  this.$element = $(element);
810
851
  //since 1.4.1 container do not use data-* directly as they already merged into options.
@@ -837,9 +878,23 @@ Applied as jQuery method.
837
878
  var $target = $(e.target), i,
838
879
  exclude_classes = ['.editable-container',
839
880
  '.ui-datepicker-header',
881
+ '.datepicker', //in inline mode datepicker is rendered into body
840
882
  '.modal-backdrop',
841
883
  '.bootstrap-wysihtml5-insert-image-modal',
842
- '.bootstrap-wysihtml5-insert-link-modal'];
884
+ '.bootstrap-wysihtml5-insert-link-modal'
885
+ ];
886
+
887
+ //check if element is detached. It occurs when clicking in bootstrap datepicker
888
+ if (!$.contains(document.documentElement, e.target)) {
889
+ return;
890
+ }
891
+
892
+ //for some reason FF 20 generates extra event (click) in select2 widget with e.target = document
893
+ //we need to filter it via construction below. See https://github.com/vitalets/x-editable/issues/199
894
+ //Possibly related to http://stackoverflow.com/questions/10119793/why-does-firefox-react-differently-from-webkit-and-ie-to-click-event-on-selec
895
+ if($target.is(document)) {
896
+ return;
897
+ }
843
898
 
844
899
  //if click inside one of exclude classes --> no nothing
845
900
  for(i=0; i<exclude_classes.length; i++) {
@@ -860,6 +915,11 @@ Applied as jQuery method.
860
915
  splitOptions: function() {
861
916
  this.containerOptions = {};
862
917
  this.formOptions = {};
918
+
919
+ if(!$.fn[this.containerName]) {
920
+ throw new Error(this.containerName + ' not found. Have you included corresponding js file?');
921
+ }
922
+
863
923
  var cDef = $.fn[this.containerName].defaults;
864
924
  //keys defined in container defaults go to container, others go to form
865
925
  for(var k in this.options) {
@@ -884,6 +944,7 @@ Applied as jQuery method.
884
944
  return this.$element.data(this.containerDataName || this.containerName);
885
945
  },
886
946
 
947
+ /* call native method of underlying container, e.g. this.$element.popover('method') */
887
948
  call: function() {
888
949
  this.$element[this.containerName].apply(this.$element, arguments);
889
950
  },
@@ -904,17 +965,21 @@ Applied as jQuery method.
904
965
  resize: $.proxy(this.setPosition, this), //this allows to re-position container when form size is changed
905
966
  rendered: $.proxy(function(){
906
967
  /**
907
- Fired when container is shown and form is rendered (for select will wait for loading dropdown options)
968
+ Fired when container is shown and form is rendered (for select will wait for loading dropdown options).
969
+ **Note:** Bootstrap popover has own `shown` event that now cannot be separated from x-editable's one.
970
+ The workaround is to check `arguments.length` that is always `2` for x-editable.
908
971
 
909
972
  @event shown
910
973
  @param {Object} event event object
911
974
  @example
912
- $('#username').on('shown', function() {
913
- var editable = $(this).data('editable');
975
+ $('#username').on('shown', function(e, editable) {
914
976
  editable.input.$input.val('overwriting value of input..');
915
977
  });
916
978
  **/
917
- this.$element.triggerHandler('shown');
979
+ /*
980
+ TODO: added second param mainly to distinguish from bootstrap's shown event. It's a hotfix that will be solved in future versions via namespaced events.
981
+ */
982
+ this.$element.triggerHandler('shown', this);
918
983
  }, this)
919
984
  })
920
985
  .editableform('render');
@@ -935,7 +1000,7 @@ Applied as jQuery method.
935
1000
 
936
1001
  //show container itself
937
1002
  this.innerShow();
938
- this.tip().addClass('editable-container');
1003
+ this.tip().addClass(this.containerClass);
939
1004
 
940
1005
  /*
941
1006
  Currently, form is re-rendered on every show.
@@ -980,11 +1045,13 @@ Applied as jQuery method.
980
1045
  this.innerHide();
981
1046
 
982
1047
  /**
983
- Fired when container was hidden. It occurs on both save or cancel.
1048
+ Fired when container was hidden. It occurs on both save or cancel.
1049
+ **Note:** Bootstrap popover has own `hidden` event that now cannot be separated from x-editable's one.
1050
+ The workaround is to check `arguments.length` that is always `2` for x-editable.
984
1051
 
985
1052
  @event hidden
986
1053
  @param {object} event event object
987
- @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code>
1054
+ @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|manual</code>
988
1055
  @example
989
1056
  $('#username').on('hidden', function(e, reason) {
990
1057
  if(reason === 'save' || reason === 'cancel') {
@@ -993,7 +1060,7 @@ Applied as jQuery method.
993
1060
  }
994
1061
  });
995
1062
  **/
996
- this.$element.triggerHandler('hidden', reason);
1063
+ this.$element.triggerHandler('hidden', reason || 'manual');
997
1064
  },
998
1065
 
999
1066
  /* internal show method. To be overwritten in child classes */
@@ -1246,16 +1313,18 @@ Applied as jQuery method.
1246
1313
  * ---------------------
1247
1314
  */
1248
1315
  (function ($) {
1316
+ "use strict";
1249
1317
 
1250
1318
  //copy prototype from EditableContainer
1251
1319
  //extend methods
1252
1320
  $.extend($.fn.editableContainer.Inline.prototype, $.fn.editableContainer.Popup.prototype, {
1253
1321
  containerName: 'editableform',
1254
1322
  innerCss: '.editable-inline',
1323
+ containerClass: 'editable-container editable-inline', //css class applied to container element
1255
1324
 
1256
1325
  initContainer: function(){
1257
1326
  //container is <span> element
1258
- this.$tip = $('<span></span>').addClass('editable-inline');
1327
+ this.$tip = $('<span></span>');
1259
1328
 
1260
1329
  //convert anim to miliseconds (int)
1261
1330
  if(!this.options.anim) {
@@ -1300,6 +1369,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1300
1369
  @uses editableContainer
1301
1370
  **/
1302
1371
  (function ($) {
1372
+ "use strict";
1303
1373
 
1304
1374
  var Editable = function (element, options) {
1305
1375
  this.$element = $(element);
@@ -1394,7 +1464,8 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1394
1464
  this.enable();
1395
1465
  }
1396
1466
  /**
1397
- Fired when element was initialized by editable method.
1467
+ Fired when element was initialized by `$().editable()` method.
1468
+ Please note that you should setup `init` handler **before** applying `editable`.
1398
1469
 
1399
1470
  @event init
1400
1471
  @param {Object} event event object
@@ -1404,6 +1475,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1404
1475
  $('#username').on('init', function(e, editable) {
1405
1476
  alert('initialized ' + editable.options.name);
1406
1477
  });
1478
+ $('#username').editable();
1407
1479
  **/
1408
1480
  this.$element.triggerHandler('init', this);
1409
1481
  }, this));
@@ -1710,6 +1782,8 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1710
1782
  @method destroy()
1711
1783
  **/
1712
1784
  destroy: function() {
1785
+ this.disable();
1786
+
1713
1787
  if(this.container) {
1714
1788
  this.container.destroy();
1715
1789
  }
@@ -1721,8 +1795,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1721
1795
 
1722
1796
  this.$element.off("save.internal");
1723
1797
 
1724
- this.$element.removeClass('editable');
1725
- this.$element.removeClass('editable-open');
1798
+ this.$element.removeClass('editable editable-open editable-disabled');
1726
1799
  this.$element.removeData('editable');
1727
1800
  }
1728
1801
  };
@@ -2029,7 +2102,8 @@ To create your own input you can inherit from this class.
2029
2102
  @class abstractinput
2030
2103
  **/
2031
2104
  (function ($) {
2032
-
2105
+ "use strict";
2106
+
2033
2107
  //types
2034
2108
  $.fn.editabletypes = {};
2035
2109
 
@@ -2212,7 +2286,10 @@ To create your own input you can inherit from this class.
2212
2286
  inputclass: 'input-medium',
2213
2287
  //scope for external methods (e.g. source defined as function)
2214
2288
  //for internal use only
2215
- scope: null
2289
+ scope: null,
2290
+
2291
+ //need to re-declare showbuttons here to get it's value from common config (passed only options existing in defaults)
2292
+ showbuttons: true
2216
2293
  };
2217
2294
 
2218
2295
  $.extend($.fn.editabletypes, {abstractinput: AbstractInput});
@@ -2226,7 +2303,8 @@ List - abstract class for inputs that have source option loaded from js array or
2226
2303
  @extends abstractinput
2227
2304
  **/
2228
2305
  (function ($) {
2229
-
2306
+ "use strict";
2307
+
2230
2308
  var List = function (options) {
2231
2309
 
2232
2310
  };
@@ -2555,6 +2633,8 @@ $(function(){
2555
2633
  </script>
2556
2634
  **/
2557
2635
  (function ($) {
2636
+ "use strict";
2637
+
2558
2638
  var Text = function (options) {
2559
2639
  this.init('text', options, Text.defaults);
2560
2640
  };
@@ -2604,18 +2684,17 @@ $(function(){
2604
2684
  },
2605
2685
 
2606
2686
  postrender: function() {
2687
+ /*
2688
+ //now `clear` is positioned via css
2607
2689
  if(this.$clear) {
2608
2690
  //can position clear button only here, when form is shown and height can be calculated
2609
- var h = this.$input.outerHeight() || 20,
2691
+ // var h = this.$input.outerHeight(true) || 20,
2692
+ var h = this.$clear.parent().height(),
2610
2693
  delta = (h - this.$clear.height()) / 2;
2611
-
2612
- //workaround for plain-popup
2613
- if(delta < 3) {
2614
- delta = 3;
2615
- }
2616
2694
 
2617
- this.$clear.css({bottom: delta, right: delta});
2618
- }
2695
+ //this.$clear.css({bottom: delta, right: delta});
2696
+ }
2697
+ */
2619
2698
  },
2620
2699
 
2621
2700
  //show / hide clear button
@@ -2690,7 +2769,8 @@ $(function(){
2690
2769
  </script>
2691
2770
  **/
2692
2771
  (function ($) {
2693
-
2772
+ "use strict";
2773
+
2694
2774
  var Textarea = function (options) {
2695
2775
  this.init('textarea', options, Textarea.defaults);
2696
2776
  };
@@ -2802,7 +2882,8 @@ $(function(){
2802
2882
  </script>
2803
2883
  **/
2804
2884
  (function ($) {
2805
-
2885
+ "use strict";
2886
+
2806
2887
  var Select = function (options) {
2807
2888
  this.init('select', options, Select.defaults);
2808
2889
  };
@@ -2891,7 +2972,8 @@ $(function(){
2891
2972
  </script>
2892
2973
  **/
2893
2974
  (function ($) {
2894
-
2975
+ "use strict";
2976
+
2895
2977
  var Checklist = function (options) {
2896
2978
  this.init('checklist', options, Checklist.defaults);
2897
2979
  };
@@ -2934,6 +3016,8 @@ $(function(){
2934
3016
  value = str.split(reg);
2935
3017
  } else if($.isArray(str)) {
2936
3018
  value = str;
3019
+ } else {
3020
+ value = [str];
2937
3021
  }
2938
3022
  return value;
2939
3023
  },
@@ -3059,6 +3143,8 @@ $(function(){
3059
3143
  Password
3060
3144
  */
3061
3145
  (function ($) {
3146
+ "use strict";
3147
+
3062
3148
  var Password = function (options) {
3063
3149
  this.init('password', options, Password.defaults);
3064
3150
  };
@@ -3088,6 +3174,8 @@ Password
3088
3174
  Email
3089
3175
  */
3090
3176
  (function ($) {
3177
+ "use strict";
3178
+
3091
3179
  var Email = function (options) {
3092
3180
  this.init('email', options, Email.defaults);
3093
3181
  };
@@ -3103,6 +3191,8 @@ Email
3103
3191
  Url
3104
3192
  */
3105
3193
  (function ($) {
3194
+ "use strict";
3195
+
3106
3196
  var Url = function (options) {
3107
3197
  this.init('url', options, Url.defaults);
3108
3198
  };
@@ -3118,6 +3208,8 @@ Url
3118
3208
  Tel
3119
3209
  */
3120
3210
  (function ($) {
3211
+ "use strict";
3212
+
3121
3213
  var Tel = function (options) {
3122
3214
  this.init('tel', options, Tel.defaults);
3123
3215
  };
@@ -3133,6 +3225,8 @@ Tel
3133
3225
  Number
3134
3226
  */
3135
3227
  (function ($) {
3228
+ "use strict";
3229
+
3136
3230
  var NumberInput = function (options) {
3137
3231
  this.init('number', options, NumberInput.defaults);
3138
3232
  };
@@ -3143,7 +3237,21 @@ Number
3143
3237
  this.setAttr('min');
3144
3238
  this.setAttr('max');
3145
3239
  this.setAttr('step');
3146
- }
3240
+ },
3241
+ postrender: function() {
3242
+ if(this.$clear) {
3243
+ //increase right ffset for up/down arrows
3244
+ this.$clear.css({right: 24});
3245
+ /*
3246
+ //can position clear button only here, when form is shown and height can be calculated
3247
+ var h = this.$input.outerHeight(true) || 20,
3248
+ delta = (h - this.$clear.height()) / 2;
3249
+
3250
+ //add 12px to offset right for up/down arrows
3251
+ this.$clear.css({top: delta, right: delta + 16});
3252
+ */
3253
+ }
3254
+ }
3147
3255
  });
3148
3256
  NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
3149
3257
  tpl: '<input type="number">',
@@ -3160,6 +3268,8 @@ Number
3160
3268
  Range (inherit from number)
3161
3269
  */
3162
3270
  (function ($) {
3271
+ "use strict";
3272
+
3163
3273
  var Range = function (options) {
3164
3274
  this.init('range', options, Range.defaults);
3165
3275
  };
@@ -3195,6 +3305,10 @@ You should manually include select2 distributive:
3195
3305
  <link href="select2/select2.css" rel="stylesheet" type="text/css"></link>
3196
3306
  <script src="select2/select2.js"></script>
3197
3307
 
3308
+ For make it **Bootstrap-styled** you can use css from [here](https://github.com/t0m/select2-bootstrap-css):
3309
+
3310
+ <link href="select2-bootstrap.css" rel="stylesheet" type="text/css"></link>
3311
+
3198
3312
  **Note:** currently `ajax` source for select2 is not supported, as it's not possible to load it in closed select2 state.
3199
3313
  The solution is to load source manually and assign statically.
3200
3314
 
@@ -3220,7 +3334,8 @@ $(function(){
3220
3334
  </script>
3221
3335
  **/
3222
3336
  (function ($) {
3223
-
3337
+ "use strict";
3338
+
3224
3339
  var Constructor = function (options) {
3225
3340
  this.init('select2', options, Constructor.defaults);
3226
3341
 
@@ -3422,8 +3537,9 @@ $(function(){
3422
3537
  $.fn.editabletypes.select2 = Constructor;
3423
3538
 
3424
3539
  }(window.jQuery));
3540
+
3425
3541
  /**
3426
- * Combodate - 1.0.2
3542
+ * Combodate - 1.0.3
3427
3543
  * Dropdown date and time picker.
3428
3544
  * Converts text input into dropdowns to pick day, month, year, hour, minute and second.
3429
3545
  * Uses momentjs as datetime library http://momentjs.com.
@@ -3530,7 +3646,7 @@ $(function(){
3530
3646
  relTime;
3531
3647
 
3532
3648
  if(this.options.firstItem === 'name') {
3533
- //need both to suuport moment ver < 2 and >= 2
3649
+ //need both to support moment ver < 2 and >= 2
3534
3650
  relTime = moment.relativeTime || moment.langData()._relativeTime;
3535
3651
  var header = typeof relTime[key] === 'function' ? relTime[key](1, true, key, false) : relTime[key];
3536
3652
  //take last entry (see momentjs lang files structure)
@@ -3595,13 +3711,16 @@ $(function(){
3595
3711
  fill year
3596
3712
  */
3597
3713
  fillYear: function() {
3598
- var items = this.initItems('y'), name, i,
3714
+ var items = [], name, i,
3599
3715
  longNames = this.options.template.indexOf('YYYY') !== -1;
3600
-
3716
+
3601
3717
  for(i=this.options.maxYear; i>=this.options.minYear; i--) {
3602
3718
  name = longNames ? i : (i+'').substring(2);
3603
- items.push([i, name]);
3604
- }
3719
+ items[this.options.yearDescending ? 'push' : 'unshift']([i, name]);
3720
+ }
3721
+
3722
+ items = this.initItems('y').concat(items);
3723
+
3605
3724
  return items;
3606
3725
  },
3607
3726
 
@@ -3723,6 +3842,22 @@ $(function(){
3723
3842
  that = this,
3724
3843
  values = {};
3725
3844
 
3845
+ //function to find nearest value in select options
3846
+ function getNearest($select, value) {
3847
+ var delta = {};
3848
+ $select.children('option').each(function(i, opt){
3849
+ var optValue = $(opt).attr('value'),
3850
+ distance;
3851
+
3852
+ if(optValue === '') return;
3853
+ distance = Math.abs(optValue - value);
3854
+ if(typeof delta.distance === 'undefined' || distance < delta.distance) {
3855
+ delta = {value: optValue, distance: distance};
3856
+ }
3857
+ });
3858
+ return delta.value;
3859
+ }
3860
+
3726
3861
  if(dt.isValid()) {
3727
3862
  //read values from date object
3728
3863
  $.each(this.map, function(k, v) {
@@ -3742,7 +3877,17 @@ $(function(){
3742
3877
  }
3743
3878
 
3744
3879
  $.each(values, function(k, v) {
3880
+ //call val() for each existing combo, e.g. this.$hour.val()
3745
3881
  if(that['$'+k]) {
3882
+
3883
+ if(k === 'minute' && that.options.minuteStep > 1 && that.options.roundTime) {
3884
+ v = getNearest(that['$'+k], v);
3885
+ }
3886
+
3887
+ if(k === 'second' && that.options.secondStep > 1 && that.options.roundTime) {
3888
+ v = getNearest(that['$'+k], v);
3889
+ }
3890
+
3746
3891
  that['$'+k].val(v);
3747
3892
  }
3748
3893
  });
@@ -3817,10 +3962,12 @@ $(function(){
3817
3962
  value: null,
3818
3963
  minYear: 1970,
3819
3964
  maxYear: 2015,
3965
+ yearDescending: true,
3820
3966
  minuteStep: 5,
3821
3967
  secondStep: 1,
3822
3968
  firstItem: 'empty', //'name', 'empty', 'none'
3823
- errorClass: null
3969
+ errorClass: null,
3970
+ roundTime: true //whether to round minutes and seconds if step > 1
3824
3971
  };
3825
3972
 
3826
3973
  }(window.jQuery));
@@ -3865,7 +4012,8 @@ $(function(){
3865
4012
  /*global moment*/
3866
4013
 
3867
4014
  (function ($) {
3868
-
4015
+ "use strict";
4016
+
3869
4017
  var Constructor = function (options) {
3870
4018
  this.init('combodate', options, Constructor.defaults);
3871
4019
 
@@ -4017,8 +4165,9 @@ $(function(){
4017
4165
  Editableform based on Twitter Bootstrap
4018
4166
  */
4019
4167
  (function ($) {
4168
+ "use strict";
4020
4169
 
4021
- $.extend($.fn.editableform.Constructor.prototype, {
4170
+ $.extend($.fn.editableform.Constructor.prototype, {
4022
4171
  initTemplate: function() {
4023
4172
  this.$form = $($.fn.editableform.template);
4024
4173
  this.$form.find('.editable-error-block').addClass('help-block');
@@ -4040,12 +4189,13 @@ Editableform based on Twitter Bootstrap
4040
4189
  * requires bootstrap-popover.js
4041
4190
  */
4042
4191
  (function ($) {
4192
+ "use strict";
4043
4193
 
4044
4194
  //extend methods
4045
4195
  $.extend($.fn.editableContainer.Popup.prototype, {
4046
4196
  containerName: 'popover',
4047
4197
  //for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content)
4048
- innerCss: $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content',
4198
+ innerCss: $.fn.popover && $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content',
4049
4199
 
4050
4200
  initContainer: function(){
4051
4201
  $.extend(this.containerOptions, {
@@ -4174,7 +4324,8 @@ $(function(){
4174
4324
  </script>
4175
4325
  **/
4176
4326
  (function ($) {
4177
-
4327
+ "use strict";
4328
+
4178
4329
  var Date = function (options) {
4179
4330
  this.init('date', options, Date.defaults);
4180
4331
  this.initPicker(options, Date.defaults);
@@ -4258,6 +4409,9 @@ $(function(){
4258
4409
  clear: function() {
4259
4410
  this.$input.data('datepicker').date = null;
4260
4411
  this.$input.find('.active').removeClass('active');
4412
+ if(!this.options.showbuttons) {
4413
+ this.$input.closest('form').submit();
4414
+ }
4261
4415
  },
4262
4416
 
4263
4417
  autosubmit: function() {
@@ -4357,7 +4511,8 @@ Automatically shown in inline mode.
4357
4511
  @since 1.4.0
4358
4512
  **/
4359
4513
  (function ($) {
4360
-
4514
+ "use strict";
4515
+
4361
4516
  var DateField = function (options) {
4362
4517
  this.init('datefield', options, DateField.defaults);
4363
4518
  this.initPicker(options, DateField.defaults);
@@ -4468,13 +4623,11 @@ Automatically shown in inline mode.
4468
4623
  this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy');
4469
4624
  this.isInline = false;
4470
4625
  this.isInput = this.element.is('input');
4471
- this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
4626
+ this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false;
4472
4627
  this.hasInput = this.component && this.element.find('input').length;
4473
4628
  if(this.component && this.component.length === 0)
4474
4629
  this.component = false;
4475
4630
 
4476
- this._attachEvents();
4477
-
4478
4631
  this.forceParse = true;
4479
4632
  if ('forceParse' in options) {
4480
4633
  this.forceParse = options.forceParse;
@@ -4482,16 +4635,12 @@ Automatically shown in inline mode.
4482
4635
  this.forceParse = this.element.data('date-force-parse');
4483
4636
  }
4484
4637
 
4485
-
4486
- this.picker = $(DPGlobal.template)
4487
- .appendTo(this.isInline ? this.element : 'body')
4488
- .on({
4489
- click: $.proxy(this.click, this),
4490
- mousedown: $.proxy(this.mousedown, this)
4491
- });
4638
+ this.picker = $(DPGlobal.template);
4639
+ this._buildEvents();
4640
+ this._attachEvents();
4492
4641
 
4493
4642
  if(this.isInline) {
4494
- this.picker.addClass('datepicker-inline');
4643
+ this.picker.addClass('datepicker-inline').appendTo(this.element);
4495
4644
  } else {
4496
4645
  this.picker.addClass('datepicker-dropdown dropdown-menu');
4497
4646
  }
@@ -4500,12 +4649,6 @@ Automatically shown in inline mode.
4500
4649
  this.picker.find('.prev i, .next i')
4501
4650
  .toggleClass('icon-arrow-left icon-arrow-right');
4502
4651
  }
4503
- $(document).on('mousedown', function (e) {
4504
- // Clicked outside the datepicker, hide it
4505
- if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
4506
- that.hide();
4507
- }
4508
- });
4509
4652
 
4510
4653
  this.autoclose = false;
4511
4654
  if ('autoclose' in options) {
@@ -4565,6 +4708,8 @@ Automatically shown in inline mode.
4565
4708
  return parseInt(val) + 1;
4566
4709
  });
4567
4710
 
4711
+ this._allow_update = false;
4712
+
4568
4713
  this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
4569
4714
  this.weekEnd = ((this.weekStart + 6) % 7);
4570
4715
  this.startDate = -Infinity;
@@ -4575,6 +4720,9 @@ Automatically shown in inline mode.
4575
4720
  this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled'));
4576
4721
  this.fillDow();
4577
4722
  this.fillMonths();
4723
+
4724
+ this._allow_update = true;
4725
+
4578
4726
  this.update();
4579
4727
  this.showMode();
4580
4728
 
@@ -4587,8 +4735,22 @@ Automatically shown in inline mode.
4587
4735
  constructor: Datepicker,
4588
4736
 
4589
4737
  _events: [],
4590
- _attachEvents: function(){
4591
- this._detachEvents();
4738
+ _secondaryEvents: [],
4739
+ _applyEvents: function(evs){
4740
+ for (var i=0, el, ev; i<evs.length; i++){
4741
+ el = evs[i][0];
4742
+ ev = evs[i][1];
4743
+ el.on(ev);
4744
+ }
4745
+ },
4746
+ _unapplyEvents: function(evs){
4747
+ for (var i=0, el, ev; i<evs.length; i++){
4748
+ el = evs[i][0];
4749
+ ev = evs[i][1];
4750
+ el.off(ev);
4751
+ }
4752
+ },
4753
+ _buildEvents: function(){
4592
4754
  if (this.isInput) { // single input
4593
4755
  this._events = [
4594
4756
  [this.element, {
@@ -4611,9 +4773,9 @@ Automatically shown in inline mode.
4611
4773
  }]
4612
4774
  ];
4613
4775
  }
4614
- else if (this.element.is('div')) { // inline datepicker
4615
- this.isInline = true;
4616
- }
4776
+ else if (this.element.is('div')) { // inline datepicker
4777
+ this.isInline = true;
4778
+ }
4617
4779
  else {
4618
4780
  this._events = [
4619
4781
  [this.element, {
@@ -4621,29 +4783,47 @@ Automatically shown in inline mode.
4621
4783
  }]
4622
4784
  ];
4623
4785
  }
4624
- for (var i=0, el, ev; i<this._events.length; i++){
4625
- el = this._events[i][0];
4626
- ev = this._events[i][1];
4627
- el.on(ev);
4628
- }
4786
+
4787
+ this._secondaryEvents = [
4788
+ [this.picker, {
4789
+ click: $.proxy(this.click, this)
4790
+ }],
4791
+ [$(window), {
4792
+ resize: $.proxy(this.place, this)
4793
+ }],
4794
+ [$(document), {
4795
+ mousedown: $.proxy(function (e) {
4796
+ // Clicked outside the datepicker, hide it
4797
+ if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
4798
+ this.hide();
4799
+ }
4800
+ }, this)
4801
+ }]
4802
+ ];
4803
+ },
4804
+ _attachEvents: function(){
4805
+ this._detachEvents();
4806
+ this._applyEvents(this._events);
4629
4807
  },
4630
4808
  _detachEvents: function(){
4631
- for (var i=0, el, ev; i<this._events.length; i++){
4632
- el = this._events[i][0];
4633
- ev = this._events[i][1];
4634
- el.off(ev);
4635
- }
4636
- this._events = [];
4809
+ this._unapplyEvents(this._events);
4810
+ },
4811
+ _attachSecondaryEvents: function(){
4812
+ this._detachSecondaryEvents();
4813
+ this._applyEvents(this._secondaryEvents);
4814
+ },
4815
+ _detachSecondaryEvents: function(){
4816
+ this._unapplyEvents(this._secondaryEvents);
4637
4817
  },
4638
4818
 
4639
4819
  show: function(e) {
4820
+ if (!this.isInline)
4821
+ this.picker.appendTo('body');
4640
4822
  this.picker.show();
4641
4823
  this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
4642
- this.update();
4643
4824
  this.place();
4644
- $(window).on('resize', $.proxy(this.place, this));
4645
- if (e ) {
4646
- e.stopPropagation();
4825
+ this._attachSecondaryEvents();
4826
+ if (e) {
4647
4827
  e.preventDefault();
4648
4828
  }
4649
4829
  this.element.trigger({
@@ -4655,13 +4835,10 @@ Automatically shown in inline mode.
4655
4835
  hide: function(e){
4656
4836
  if(this.isInline) return;
4657
4837
  if (!this.picker.is(':visible')) return;
4658
- this.picker.hide();
4659
- $(window).off('resize', this.place);
4838
+ this.picker.hide().detach();
4839
+ this._detachSecondaryEvents();
4660
4840
  this.viewMode = this.startViewMode;
4661
4841
  this.showMode();
4662
- if (!this.isInput) {
4663
- $(document).off('mousedown', this.hide);
4664
- }
4665
4842
 
4666
4843
  if (
4667
4844
  this.forceParse &&
@@ -4678,9 +4855,14 @@ Automatically shown in inline mode.
4678
4855
  },
4679
4856
 
4680
4857
  remove: function() {
4858
+ this.hide();
4681
4859
  this._detachEvents();
4860
+ this._detachSecondaryEvents();
4682
4861
  this.picker.remove();
4683
4862
  delete this.element.data().datepicker;
4863
+ if (!this.isInput) {
4864
+ delete this.element.data().date;
4865
+ }
4684
4866
  },
4685
4867
 
4686
4868
  getDate: function() {
@@ -4754,7 +4936,7 @@ Automatically shown in inline mode.
4754
4936
  var zIndex = parseInt(this.element.parents().filter(function() {
4755
4937
  return $(this).css('z-index') != 'auto';
4756
4938
  }).first().css('z-index'))+10;
4757
- var offset = this.component ? this.component.offset() : this.element.offset();
4939
+ var offset = this.component ? this.component.parent().offset() : this.element.offset();
4758
4940
  var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true);
4759
4941
  this.picker.css({
4760
4942
  top: offset.top + height,
@@ -4763,7 +4945,10 @@ Automatically shown in inline mode.
4763
4945
  });
4764
4946
  },
4765
4947
 
4948
+ _allow_update: true,
4766
4949
  update: function(){
4950
+ if (!this._allow_update) return;
4951
+
4767
4952
  var date, fromArgs = false;
4768
4953
  if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
4769
4954
  date = arguments[0];
@@ -4918,6 +5103,8 @@ Automatically shown in inline mode.
4918
5103
  },
4919
5104
 
4920
5105
  updateNavArrows: function() {
5106
+ if (!this._allow_update) return;
5107
+
4921
5108
  var d = new Date(this.viewDate),
4922
5109
  year = d.getUTCFullYear(),
4923
5110
  month = d.getUTCMonth();
@@ -4951,7 +5138,6 @@ Automatically shown in inline mode.
4951
5138
  },
4952
5139
 
4953
5140
  click: function(e) {
4954
- e.stopPropagation();
4955
5141
  e.preventDefault();
4956
5142
  var target = $(e.target).closest('span, td, th');
4957
5143
  if (target.length == 1) {
@@ -5441,6 +5627,300 @@ Automatically shown in inline mode.
5441
5627
 
5442
5628
  }( window.jQuery );
5443
5629
 
5630
+ /**
5631
+ Bootstrap-datetimepicker.
5632
+ Based on [smalot bootstrap-datetimepicker plugin](https://github.com/smalot/bootstrap-datetimepicker).
5633
+ Before usage you should manually include dependent js and css:
5634
+
5635
+ <link href="css/datetimepicker.css" rel="stylesheet" type="text/css"></link>
5636
+ <script src="js/bootstrap-datetimepicker.js"></script>
5637
+
5638
+ For **i18n** you should include js file from here: https://github.com/smalot/bootstrap-datetimepicker/tree/master/js/locales
5639
+ and set `language` option.
5640
+
5641
+ @class datetime
5642
+ @extends abstractinput
5643
+ @final
5644
+ @since 1.4.4
5645
+ @example
5646
+ <a href="#" id="last_seen" data-type="datetime" data-pk="1" data-url="/post" title="Select date & time">15/03/2013 12:45</a>
5647
+ <script>
5648
+ $(function(){
5649
+ $('#last_seen').editable({
5650
+ format: 'yyyy-mm-dd hh:ii',
5651
+ viewformat: 'dd/mm/yyyy hh:ii',
5652
+ datetimepicker: {
5653
+ weekStart: 1
5654
+ }
5655
+ }
5656
+ });
5657
+ });
5658
+ </script>
5659
+ **/
5660
+ (function ($) {
5661
+ "use strict";
5662
+
5663
+ var DateTime = function (options) {
5664
+ this.init('datetime', options, DateTime.defaults);
5665
+ this.initPicker(options, DateTime.defaults);
5666
+ };
5667
+
5668
+ $.fn.editableutils.inherit(DateTime, $.fn.editabletypes.abstractinput);
5669
+
5670
+ $.extend(DateTime.prototype, {
5671
+ initPicker: function(options, defaults) {
5672
+ //'format' is set directly from settings or data-* attributes
5673
+
5674
+ //by default viewformat equals to format
5675
+ if(!this.options.viewformat) {
5676
+ this.options.viewformat = this.options.format;
5677
+ }
5678
+
5679
+ //overriding datetimepicker config (as by default jQuery extend() is not recursive)
5680
+ //since 1.4 datetimepicker internally uses viewformat instead of format. Format is for submit only
5681
+ this.options.datetimepicker = $.extend({}, defaults.datetimepicker, options.datetimepicker, {
5682
+ format: this.options.viewformat
5683
+ });
5684
+
5685
+ //language
5686
+ this.options.datetimepicker.language = this.options.datetimepicker.language || 'en';
5687
+
5688
+ //store DPglobal
5689
+ this.dpg = $.fn.datetimepicker.DPGlobal;
5690
+
5691
+ //store parsed formats
5692
+ this.parsedFormat = this.dpg.parseFormat(this.options.format, this.options.formatType);
5693
+ this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat, this.options.formatType);
5694
+
5695
+ //
5696
+ this.options.datetimepicker.startView = this.options.startView;
5697
+ this.options.datetimepicker.minView = this.options.minView;
5698
+ this.options.datetimepicker.maxView = this.options.maxView;
5699
+ },
5700
+
5701
+ render: function () {
5702
+ this.$input.datetimepicker(this.options.datetimepicker);
5703
+
5704
+ //"clear" link
5705
+ if(this.options.clear) {
5706
+ this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
5707
+ e.preventDefault();
5708
+ e.stopPropagation();
5709
+ this.clear();
5710
+ }, this));
5711
+
5712
+ this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear));
5713
+ }
5714
+ },
5715
+
5716
+ value2html: function(value, element) {
5717
+ //formatDate works with UTCDate!
5718
+ var text = value ? this.dpg.formatDate(this.toUTC(value), this.parsedViewFormat, this.options.datetimepicker.language, this.options.formatType) : '';
5719
+ if(element) {
5720
+ DateTime.superclass.value2html(text, element);
5721
+ } else {
5722
+ return text;
5723
+ }
5724
+ },
5725
+
5726
+ html2value: function(html) {
5727
+ //parseDate return utc date!
5728
+ var value = html ? this.dpg.parseDate(html, this.parsedViewFormat, this.options.datetimepicker.language, this.options.formatType) : null;
5729
+ return value ? this.fromUTC(value) : null;
5730
+ },
5731
+
5732
+ value2str: function(value) {
5733
+ //formatDate works with UTCDate!
5734
+ return value ? this.dpg.formatDate(this.toUTC(value), this.parsedFormat, this.options.datetimepicker.language, this.options.formatType) : '';
5735
+ },
5736
+
5737
+ str2value: function(str) {
5738
+ //parseDate return utc date!
5739
+ var value = str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datetimepicker.language, this.options.formatType) : null;
5740
+ return value ? this.fromUTC(value) : null;
5741
+ },
5742
+
5743
+ value2submit: function(value) {
5744
+ return this.value2str(value);
5745
+ },
5746
+
5747
+ value2input: function(value) {
5748
+ if(value) {
5749
+ this.$input.data('datetimepicker').setDate(value);
5750
+ }
5751
+ },
5752
+
5753
+ input2value: function() {
5754
+ //date may be cleared, in that case getDate() triggers error
5755
+ var dt = this.$input.data('datetimepicker');
5756
+ return dt.date ? dt.getDate() : null;
5757
+ },
5758
+
5759
+ activate: function() {
5760
+ },
5761
+
5762
+ clear: function() {
5763
+ this.$input.data('datetimepicker').date = null;
5764
+ this.$input.find('.active').removeClass('active');
5765
+ if(!this.options.showbuttons) {
5766
+ this.$input.closest('form').submit();
5767
+ }
5768
+ },
5769
+
5770
+ autosubmit: function() {
5771
+ this.$input.on('mouseup', '.minute', function(e){
5772
+ var $form = $(this).closest('form');
5773
+ setTimeout(function() {
5774
+ $form.submit();
5775
+ }, 200);
5776
+ });
5777
+ },
5778
+
5779
+ //convert date from local to utc
5780
+ toUTC: function(value) {
5781
+ return value ? new Date(value.valueOf() - value.getTimezoneOffset() * 60000) : value;
5782
+ },
5783
+
5784
+ //convert date from utc to local
5785
+ fromUTC: function(value) {
5786
+ return value ? new Date(value.valueOf() + value.getTimezoneOffset() * 60000) : value;
5787
+ }
5788
+
5789
+ });
5790
+
5791
+ DateTime.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
5792
+ /**
5793
+ @property tpl
5794
+ @default <div></div>
5795
+ **/
5796
+ tpl:'<div class="editable-date well"></div>',
5797
+ /**
5798
+ @property inputclass
5799
+ @default null
5800
+ **/
5801
+ inputclass: null,
5802
+ /**
5803
+ Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
5804
+ Possible tokens are: <code>d, dd, m, mm, yy, yyyy, h, i</code>
5805
+
5806
+ @property format
5807
+ @type string
5808
+ @default yyyy-mm-dd hh:ii
5809
+ **/
5810
+ format:'yyyy-mm-dd hh:ii',
5811
+ formatType:'standard',
5812
+ /**
5813
+ Format used for displaying date. Also applied when converting date from element's text on init.
5814
+ If not specified equals to <code>format</code>
5815
+
5816
+ @property viewformat
5817
+ @type string
5818
+ @default null
5819
+ **/
5820
+ viewformat: null,
5821
+ /**
5822
+ Configuration of datetimepicker.
5823
+ Full list of options: https://github.com/smalot/bootstrap-datetimepicker
5824
+
5825
+ @property datetimepicker
5826
+ @type object
5827
+ @default { }
5828
+ **/
5829
+ datetimepicker:{
5830
+ todayHighlight: false,
5831
+ autoclose: false
5832
+ },
5833
+ /**
5834
+ Text shown as clear date button.
5835
+ If <code>false</code> clear button will not be rendered.
5836
+
5837
+ @property clear
5838
+ @type boolean|string
5839
+ @default 'x clear'
5840
+ **/
5841
+ clear: '&times; clear'
5842
+ });
5843
+
5844
+ $.fn.editabletypes.datetime = DateTime;
5845
+
5846
+ }(window.jQuery));
5847
+ /**
5848
+ Bootstrap datetimefield input - datetime input for inline mode.
5849
+ Shows normal <input type="text"> and binds popup datetimepicker.
5850
+ Automatically shown in inline mode.
5851
+
5852
+ @class datetimefield
5853
+ @extends datetime
5854
+
5855
+ **/
5856
+ (function ($) {
5857
+ "use strict";
5858
+
5859
+ var DateTimeField = function (options) {
5860
+ this.init('datetimefield', options, DateTimeField.defaults);
5861
+ this.initPicker(options, DateTimeField.defaults);
5862
+ };
5863
+
5864
+ $.fn.editableutils.inherit(DateTimeField, $.fn.editabletypes.datetime);
5865
+
5866
+ $.extend(DateTimeField.prototype, {
5867
+ render: function () {
5868
+ this.$input = this.$tpl.find('input');
5869
+ this.setClass();
5870
+ this.setAttr('placeholder');
5871
+
5872
+ this.$tpl.datetimepicker(this.options.datetimepicker);
5873
+
5874
+ //need to disable original event handlers
5875
+ this.$input.off('focus keydown');
5876
+
5877
+ //update value of datepicker
5878
+ this.$input.keyup($.proxy(function(){
5879
+ this.$tpl.removeData('date');
5880
+ this.$tpl.datetimepicker('update');
5881
+ }, this));
5882
+
5883
+ },
5884
+
5885
+ value2input: function(value) {
5886
+ this.$input.val(this.value2html(value));
5887
+ this.$tpl.datetimepicker('update');
5888
+ },
5889
+
5890
+ input2value: function() {
5891
+ return this.html2value(this.$input.val());
5892
+ },
5893
+
5894
+ activate: function() {
5895
+ $.fn.editabletypes.text.prototype.activate.call(this);
5896
+ },
5897
+
5898
+ autosubmit: function() {
5899
+ //reset autosubmit to empty
5900
+ }
5901
+ });
5902
+
5903
+ DateTimeField.defaults = $.extend({}, $.fn.editabletypes.datetime.defaults, {
5904
+ /**
5905
+ @property tpl
5906
+ **/
5907
+ tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',
5908
+ /**
5909
+ @property inputclass
5910
+ @default 'input-medium'
5911
+ **/
5912
+ inputclass: 'input-medium',
5913
+
5914
+ /* datetimepicker config */
5915
+ datetimepicker:{
5916
+ todayHighlight: false,
5917
+ autoclose: true
5918
+ }
5919
+ });
5920
+
5921
+ $.fn.editabletypes.datetimefield = DateTimeField;
5922
+
5923
+ }(window.jQuery));
5444
5924
  /**
5445
5925
  Typeahead input (bootstrap only). Based on Twitter Bootstrap [typeahead](http://twitter.github.com/bootstrap/javascript.html#typeahead).
5446
5926
  Depending on `source` format typeahead operates in two modes:
@@ -5473,7 +5953,8 @@ $(function(){
5473
5953
  </script>
5474
5954
  **/
5475
5955
  (function ($) {
5476
-
5956
+ "use strict";
5957
+
5477
5958
  var Constructor = function (options) {
5478
5959
  this.init('typeahead', options, Constructor.defaults);
5479
5960
 
@@ -1,4 +1,4 @@
1
- /*! X-editable - v1.4.3
1
+ /*! X-editable - v1.4.4
2
2
  * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
3
  * http://github.com/vitalets/x-editable
4
4
  * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
@@ -22,7 +22,11 @@
22
22
  *display: inline;
23
23
  }
24
24
 
25
-
25
+ .editable-buttons.editable-buttons-bottom {
26
+ display: block;
27
+ margin-top: 7px;
28
+ margin-left: 0;
29
+ }
26
30
 
27
31
  .editable-input {
28
32
  vertical-align: top;
@@ -71,12 +75,20 @@
71
75
  color: red;
72
76
  }
73
77
 
78
+ /* ---- For specific types ---- */
79
+
74
80
  .editableform .editable-date {
75
81
  padding: 0;
76
82
  margin: 0;
77
83
  float: left;
78
84
  }
79
85
 
86
+ /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
87
+ .editable-inline .add-on .icon-th {
88
+ margin-top: 3px;
89
+ margin-left: 1px;
90
+ }
91
+
80
92
 
81
93
  /* checklist vertical alignment */
82
94
  .editable-checklist label input[type="checkbox"],
@@ -112,18 +124,21 @@
112
124
  position: absolute;
113
125
  opacity: 0.6;
114
126
  z-index: 100;
115
-
127
+
128
+ top: 50%;
129
+ right: 6px;
130
+ margin-top: -6px;
131
+
116
132
  }
117
133
 
118
134
  .editable-clear-x:hover {
119
135
  opacity: 1;
120
136
  }
121
- .editable-container {
137
+ .editable-container.editable-popup {
122
138
  max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
123
139
  }
124
140
 
125
141
  .editable-container.popover {
126
- /* width: 300px;*/ /* debug */
127
142
  width: auto; /* without this rule popover does not stretch */
128
143
  }
129
144
 
@@ -154,10 +169,10 @@ a.editable-click.editable-disabled:hover {
154
169
  border-bottom: none;
155
170
  }
156
171
 
157
- .editable-empty, .editable-empty:hover{
172
+ .editable-empty, .editable-empty:hover, .editable-empty:focus{
158
173
  font-style: italic;
159
174
  color: #DD1144;
160
- border-bottom: none;
175
+ /* border-bottom: none; */
161
176
  text-decoration: none;
162
177
  }
163
178
 
@@ -188,7 +203,6 @@ a.editable-click.editable-disabled:hover {
188
203
  */
189
204
  .datepicker {
190
205
  padding: 4px;
191
- margin-top: 1px;
192
206
  -webkit-border-radius: 4px;
193
207
  -moz-border-radius: 4px;
194
208
  border-radius: 4px;
@@ -291,6 +305,7 @@ a.editable-click.editable-disabled:hover {
291
305
  border-color: #fdf59a #fdf59a #fbed50;
292
306
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
293
307
  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
308
+ color: #000 !important;
294
309
  }
295
310
  .datepicker table tr td.today:hover,
296
311
  .datepicker table tr td.today:hover:hover,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootstrap-x-editable-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-17 00:00:00.000000000 Z
12
+ date: 2013-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties