diff --git a/src/editable-form/editable-form-utils.js b/src/editable-form/editable-form-utils.js index 00c6c6a..cb16236 100644 --- a/src/editable-form/editable-form-utils.js +++ b/src/editable-form/editable-form-utils.js @@ -146,7 +146,34 @@ /*jslint eqeq: false*/ return result; - } + }, + + /* + Returns input by options: type, mode. + */ + createInput: function(options) { + var TypeConstructor, typeOptions, input, + type = options.type; + + if(type === 'date' && options.mode === 'inline') { + if($.fn.editabletypes.datefield) { + type = 'datefield'; + } else if($.fn.editabletypes.dateuifield) { + type = 'dateuifield'; + } + } + + //create input of specified type. Input will be used for converting value, not in form + if(typeof $.fn.editabletypes[type] === 'function') { + TypeConstructor = $.fn.editabletypes[type]; + typeOptions = this.sliceObj(options, this.objectKeys(TypeConstructor.defaults)); + input = new TypeConstructor(typeOptions); + return input; + } else { + $.error('Unknown type: '+ type); + return false; + } + } }; -}(window.jQuery)); \ No newline at end of file +}(window.jQuery)); diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js index d7c6d02..b52e71c 100644 --- a/src/editable-form/editable-form.js +++ b/src/editable-form/editable-form.js @@ -21,18 +21,13 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc. EditableForm.prototype = { constructor: EditableForm, initInput: function() { //called once - var TypeConstructor, typeOptions; - //create input of specified type - if(typeof $.fn.editabletypes[this.options.type] === 'function') { - TypeConstructor = $.fn.editabletypes[this.options.type]; - typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); - this.input = new TypeConstructor(typeOptions); - } else { - $.error('Unknown type: '+ this.options.type); + this.input = $.fn.editableutils.createInput(this.options); + if(!this.input) { return; - } - + } + + //set initial value this.value = this.input.str2value(this.options.value); }, initTemplate: function() { diff --git a/src/element/editable-element.js b/src/element/editable-element.js index a458ba6..1faf285 100644 --- a/src/element/editable-element.js +++ b/src/element/editable-element.js @@ -15,27 +15,15 @@ Makes editable any HTML element on the page. Applied as jQuery method. Editable.prototype = { constructor: Editable, init: function () { - var TypeConstructor, - isValueByText = false, - doAutotext, - finalize; + var isValueByText = false, + doAutotext, finalize; - //editableContainer must be defined - if(!$.fn.editableContainer) { - $.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)'); - return; - } - //name this.options.name = this.options.name || this.$element.attr('id'); //create input of specified type. Input will be used for converting value, not in form - if(typeof $.fn.editabletypes[this.options.type] === 'function') { - TypeConstructor = $.fn.editabletypes[this.options.type]; - this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); - this.input = new TypeConstructor(this.typeOptions); - } else { - $.error('Unknown type: '+ this.options.type); + this.input = $.fn.editableutils.createInput(this.options); + if(!this.input) { return; } diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js index 06308ce..d9e0684 100644 --- a/src/inputs/date/date.js +++ b/src/inputs/date/date.js @@ -26,32 +26,37 @@ $(function(){ var Date = function (options) { this.init('date', options, Date.defaults); - - //set popular options directly from settings or data-* attributes - var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']); - - //overriding datepicker config (as by default jQuery extend() is not recursive) - this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker); - - //by default viewformat equals to format - if(!this.options.viewformat) { - this.options.viewformat = this.options.datepicker.format; - } - - //language - this.options.datepicker.language = this.options.datepicker.language || 'en'; - - //store DPglobal - this.dpg = $.fn.datepicker.DPGlobal; - - //store parsed formats - this.parsedFormat = this.dpg.parseFormat(this.options.datepicker.format); - this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat); + this.initPicker(); }; $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput); $.extend(Date.prototype, { + initPicker: function() { + //'format' is set directly from settings or data-* attributes + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.format; + } + + //overriding datepicker config (as by default jQuery extend() is not recursive) + //since 1.4 datepicker internally uses viewformat instead of format. Format is for submit only + this.options.datepicker = $.extend({}, Date.defaults.datepicker, this.options.datepicker, { + format: this.options.viewformat + }); + + //language + this.options.datepicker.language = this.options.datepicker.language || 'en'; + + //store DPglobal + this.dpg = $.fn.datepicker.DPGlobal; + + //store parsed formats + this.parsedFormat = this.dpg.parseFormat(this.options.format); + this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat); + }, + render: function () { Date.superclass.render.call(this); this.$input.datepicker(this.options.datepicker); diff --git a/src/inputs/date/datefield.js b/src/inputs/date/datefield.js new file mode 100644 index 0000000..7177ffa --- /dev/null +++ b/src/inputs/date/datefield.js @@ -0,0 +1,85 @@ +/** +Bootstrap datefield input - modification for inline mode. +Shows normal <input type="text"> and binds popup datepicker. +Automatically shown in inline mode. +**/ +(function ($) { + + var DateField = function (options) { + this.init('datefield', options, DateField.defaults); + this.initPicker(); + }; + + $.fn.editableutils.inherit(DateField, $.fn.editabletypes.date); + + $.extend(DateField.prototype, { + render: function () { + this.$input = $(this.options.tpl); + this.$field = this.$input.find('input'); + + if(this.options.inputclass) { + this.$field.addClass(this.options.inputclass); + } + + if (this.options.placeholder) { + this.$field.attr('placeholder', this.options.placeholder); + } + + this.$input.datepicker(this.options.datepicker); + + //need to disable original event handlers + this.$field.off('focus keyup keydown'); + + //shadow update value of datepicker + this.$field.keyup($.proxy(function(){ + this.$input.data('datepicker').date = this.input2value(); + }, this)); + }, + + value2str: function(value) { + return value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''; + }, + + value2submit: function(value) { + return value ? this.dpg.formatDate(value, this.parsedFormat, this.options.datepicker.language) : null; + }, + + value2input: function(value) { + this.$field.val(this.value2str(value)); + this.$input.datepicker('update'); + }, + + input2value: function() { + return this.html2value(this.$field.val()); + }, + + activate: function() { + if(this.$field.is(':visible')) { + this.$field.focus(); + $.fn.editableutils.setCursorPosition(this.$field.get(0), this.$field.val().length); + } + }, + + autosubmit: function() { + //reset autosubmit to empty + } + }); + + DateField.defaults = $.extend({}, $.fn.editabletypes.date.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl:'<div class="input-append date"><input class="input-small" type="text"/><span class="add-on"><i class="icon-th"></i></span></div>', + /** + @property inputclass + @default '' + **/ + inputclass: '', + datepicker: {autoclose: true}, + clear: false + }); + + $.fn.editabletypes.datefield = DateField; + +}(window.jQuery)); \ No newline at end of file diff --git a/test/loader.js b/test/loader.js index 327d64e..7ffb74f 100644 --- a/test/loader.js +++ b/test/loader.js @@ -75,6 +75,9 @@ define(function () { loadCss(require.toUrl("./bootstrap-datepicker/css/datepicker.css")); } }, + + //datefield + 'inputs/date/datefield': ['inputs/date/date'], //jqueryui 'jqueryui/js/jquery-ui-1.9.1.custom': { @@ -128,7 +131,8 @@ define(function () { if(f === 'bootstrap') { //bootstrap - shim['editable-form/editable-form'].deps.push('inputs/date/date'); +// shim['editable-form/editable-form'].deps.push('inputs/date/date'); + shim['editable-form/editable-form'].deps.push('inputs/date/datefield'); shim['element/editable-element'].deps.push('editable-form/editable-form-bootstrap'); shim['element/editable-element'].deps.push('containers/editable-popover'); } else if(f === 'jqueryui') { diff --git a/test/unit/date.js b/test/unit/date.js index bb9701a..aaf5830 100644 --- a/test/unit/date.js +++ b/test/unit/date.js @@ -109,10 +109,7 @@ $(function () { test("viewformat, init by value", function () { var dview = '15/05/1984', d = '1984-05-15', - e = $('<a href="#" data-type="date" data-pk="1" data-weekstart="1" data-value="'+d+'"></a>').appendTo('#qunit-fixture').editable({ - format: 'yyyy-mm-dd', - viewformat: 'dd/mm/yyyy' - }); + e = $('<a href="#" data-type="date" data-pk="1" data-format="yyyy-mm-dd" data-viewformat="dd/mm/yyyy" data-value="'+d+'"></a>').appendTo('#qunit-fixture').editable(); equal(frmt(e.data('editable').value, 'yyyy-mm-dd'), d, 'value correct'); equal(e.text(), dview, 'text correct');