diff --git a/.gitignore b/.gitignore index ef3f37c..a65c8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist -test/instrumented/ \ No newline at end of file +test/instrumented/ +*.nupkg \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4f9680d..09018e3 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,22 @@ X-editable changelog ============================= +Version 1.4.2 Mar 7, 2013 +---------------------------- +[enh #132] combodate options can be defined via data-combodate json string (vitalets) +[enh] source defined as function now has scope of element and can return string used as url (vitalets) +[bug #99] select2 with Hierarchical Data (kev360) +[bug #81] wysihtml5: fix inserting image (vitalets) +[bug] remove $.browser from wysihtml5 input to support jQuery 1.9 (vitalets) +[bug #142] editable poshytip jquery 1.9+ compatibility (spiderpug) +[enh #126] Update bootstrap datepicker library and add minViewMode to options (kev360) +[enh #150] select2 with showbuttons = false (vitalets) +[bug #149] datepicker not shown when showbuttons = false (vitalets) +[bug #133] clear button incorect position due to parent line-height property (vitalets) +[bug #141] data-value ignored for empty elements (vitalets) +[bug #137] fix empty class for delegated element (vitalets) +[enh #121] add support of momentjs 2.0.0 in combodate (vitalets) + Version 1.4.1 Jan 18, 2013 ---------------------------- diff --git a/Package.nuspec b/Package.nuspec new file mode 100644 index 0000000..738cf8a --- /dev/null +++ b/Package.nuspec @@ -0,0 +1,21 @@ + + + + x-editable + 1.4.2 + Vitaliy Potapov + Vitaliy Potapov + https://github.com/vitalets/x-editable/blob/master/LICENSE-MIT + http://vitalets.github.com/x-editable + false + In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery + Added support of jQuery 1.9 and several bugfixes. + Copyright 2012-2013 + edit-in-place editable bootstrap jquery + + + + + + + \ No newline at end of file diff --git a/grunt.js b/grunt.js index 373e532..18428e2 100644 --- a/grunt.js +++ b/grunt.js @@ -106,10 +106,11 @@ module.exports = function(grunt) { //module = '&module=select'; //module = '&module=text'; +//test on several jquery versions var qunit_testover = []; ['bootstrap', 'jqueryui', 'plain'].forEach(function(f){ ['popup', 'inline'].forEach(function(c){ - ['1.6.4', '1.7.1', '1.7.2', '1.8.2', '1.8.3'].forEach(function(jqver) { + ['1.7.2', '1.8.3', '1.9.1'].forEach(function(jqver) { qunit_testover.push('http://localhost:8000/test/index.html?f='+f+'&c='+c+'&jquery='+jqver+module); }); }); diff --git a/package.json b/package.json index 1bae2fe..cf6190e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "X-editable", "title": "X-editable", "description": "In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery", - "version": "1.4.1", + "version": "1.4.2", "homepage": "http://github.com/vitalets/x-editable", "author": { "name": "Vitaliy Potapov", diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js index 83cd56f..faa0cdb 100644 --- a/src/containers/editable-container.js +++ b/src/containers/editable-container.js @@ -47,7 +47,8 @@ Applied as jQuery method. } }); - //close containers when click outside + //close containers when click outside + //(mousedown could be better than click, it closes everything also on drag drop) $(document).on('click.editable', function(e) { var $target = $(e.target), i, exclude_classes = ['.editable-container', @@ -125,8 +126,8 @@ Applied as jQuery method. @param {Object} event event object @example $('#username').on('shown', function() { - var $tip = $(this).data('editableContainer').tip(); - $tip.find('input').val('overwriting value of input..'); + var editable = $(this).data('editable'); + editable.input.$input.val('overwriting value of input..'); }); **/ this.$element.triggerHandler('shown'); @@ -427,9 +428,9 @@ Applied as jQuery method. Animation speed (inline mode) @property anim @type string - @default 'fast' + @default false **/ - anim: 'fast', + anim: false, /** Mode of editable, can be `popup` or `inline` diff --git a/src/containers/editable-poshytip.js b/src/containers/editable-poshytip.js index cf846dd..ff8cb00 100644 --- a/src/containers/editable-poshytip.js +++ b/src/containers/editable-poshytip.js @@ -108,7 +108,7 @@ var tips = [], reBgImage = /^url\(["']?([^"'\)]*)["']?\);?$/i, rePNG = /\.png$/i, - ie6 = $.browser.msie && $.browser.version == 6; + ie6 = !!window.createPopup && document.documentElement.currentStyle.minWidth == 'undefined'; $.Poshytip.prototype.refresh = function(async) { if (this.disabled) diff --git a/src/editable-form/editable-form-utils.js b/src/editable-form/editable-form-utils.js index 2fc0044..89cff18 100644 --- a/src/editable-form/editable-form-utils.js +++ b/src/editable-form/editable-form-utils.js @@ -145,7 +145,7 @@ $.each(sourceData, function(i, o) { if(o.children) { - result = result.concat(that.itemsByValue(value, o.children)); + result = result.concat(that.itemsByValue(value, o.children, valueProp)); } else { /*jslint eqeq: true*/ if(isValArray) { diff --git a/src/editable-form/editable-form.css b/src/editable-form/editable-form.css index 83b43aa..d07e06a 100644 --- a/src/editable-form/editable-form.css +++ b/src/editable-form/editable-form.css @@ -5,6 +5,7 @@ .editableform .control-group { margin-bottom: 0; /* overwrites bootstrap margin */ white-space: nowrap; /* prevent wrapping buttons on new line */ + line-height: 20px; /* overwriting bootstrap line-height. See #133 */ } .editable-buttons { @@ -106,6 +107,7 @@ position: absolute; opacity: 0.6; z-index: 100; + } .editable-clear-x:hover { diff --git a/src/element/editable-element.css b/src/element/editable-element.css index 9d9eaf6..f6b09c5 100644 --- a/src/element/editable-element.css +++ b/src/element/editable-element.css @@ -28,3 +28,10 @@ a.editable-click.editable-disabled:hover { /* content: '*'*/ } +/*see https://github.com/vitalets/x-editable/issues/139 */ +.form-horizontal .editable +{ + padding-top: 5px; + display:inline-block; +} + diff --git a/src/element/editable-element.js b/src/element/editable-element.js index 0849836..3069652 100644 --- a/src/element/editable-element.js +++ b/src/element/editable-element.js @@ -26,7 +26,9 @@ Makes editable any HTML element on the page. Applied as jQuery method. //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 + //create input of specified type. Input needed already here to convert value for initial display (e.g. show text by id for select) + //also we set scope option to have access to element inside input specific callbacks (e. g. source as function) + this.options.scope = this.$element[0]; this.input = $.fn.editableutils.createInput(this.options); if(!this.input) { return; @@ -77,9 +79,19 @@ Makes editable any HTML element on the page. Applied as jQuery method. } //check conditions for autotext: - //if value was generated by text or value is empty, no sense to run autotext - doAutotext = !isValueByText && this.value !== null && this.value !== undefined; - doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length); + switch(this.options.autotext) { + case 'always': + doAutotext = true; + break; + case 'auto': + //if element text is empty and value is defined and value not generated by text --> run autotext + doAutotext = !$.trim(this.$element.text()).length && this.value !== null && this.value !== undefined && !isValueByText; + break; + default: + doAutotext = false; + } + + //depending on autotext run render() or just finilize init $.when(doAutotext ? this.render() : true).then($.proxy(function() { if(this.options.disabled) { this.disable(); @@ -115,6 +127,11 @@ Makes editable any HTML element on the page. Applied as jQuery method. this.$element.on(this.options.toggle + '.editable', selector, $.proxy(function(e){ var $target = $(e.target); if(!$target.data('editable')) { + //if delegated element initially empty, we need to clear it's text (that was manually set to `empty` by user) + //see https://github.com/vitalets/x-editable/issues/137 + if($target.hasClass(this.options.emptyclass)) { + $target.empty(); + } $target.editable(this.options).trigger(e); } }, this)); @@ -236,7 +253,7 @@ Makes editable any HTML element on the page. Applied as jQuery method. if(this.options.display === false) { return; } - + this.isEmpty = isEmpty !== undefined ? isEmpty : $.trim(this.$element.text()) === ''; //emptytext shown only for enabled @@ -457,11 +474,14 @@ Makes editable any HTML element on the page. Applied as jQuery method. return result; /** - Returns current values of editable elements. If value is null or undefined it will not be returned + Returns current values of editable elements. + Note that it returns an **object** with name-value pairs, not a value itself. It allows to get data from several elements. + If value of some editable is `null` or `undefined` it is excluded from result object. + @method getValue() @returns {Object} object of element names and values @example - $('#username, #fullname').editable('validate'); + $('#username, #fullname').editable('getValue'); // possible result: { username: "superuser", @@ -598,8 +618,20 @@ Makes editable any HTML element on the page. Applied as jQuery method. **/ autotext: 'auto', /** - Initial value of input. If not set, taken from element's text. - + Initial value of input. If not set, taken from element's text. + Note, that if element's text is empty - text is automatically generated from value and can be customized (see `autotext` option). + For example, to display currency sign: + @example + + + @property value @type mixed @default element's text @@ -610,12 +642,12 @@ Makes editable any HTML element on the page. Applied as jQuery method. If `null`, default input's display used. If `false`, no displaying methods will be called, element's text will never change. Runs under element's scope. - _Parameters:_ + _**Parameters:**_ * `value` current value to be displayed * `response` server response (if display called after ajax submit), since 1.4.0 - For **inputs with source** (select, checklist) parameters are different: + For _inputs with source_ (select, checklist) parameters are different: * `value` current value to be displayed * `sourceData` array of items for current input (e.g. dropdown items) @@ -662,10 +694,12 @@ Makes editable any HTML element on the page. Applied as jQuery method. **/ unsavedclass: 'editable-unsaved', /** - If a css selector is provided, editable will be delegated to the specified targets. + If selector is provided, editable will be delegated to the specified targets. Usefull for dynamically generated DOM elements. - **Please note**, that delegated targets can't use `emptytext` and `autotext` options, - as they are initialized after first click. + **Please note**, that delegated targets can't be initialized with `emptytext` and `autotext` options, + as they actually become editable only after first click. + You should manually set class `editable-click` to these elements. + Also, if element originally empty you should add class `editable-empty`, set `data-value=""` and write emptytext into element: @property selector @type string @@ -673,8 +707,10 @@ Makes editable any HTML element on the page. Applied as jQuery method. @default null @example
- awesome - Operator + + Empty + + Operator
+**Note:** It's better to use fresh bootstrap-wysihtml5 from it's [master branch](https://github.com/jhollingworth/bootstrap-wysihtml5/tree/master/src) as there is update for correct image insertion. + @class wysihtml5 @extends abstractinput @final @@ -35,8 +37,9 @@ $(function(){ $.extend(Wysihtml5.prototype, { render: function () { - var deferred = $.Deferred(); - + var deferred = $.Deferred(), + msieOld; + //generate unique id as it required for wysihtml5 this.$input.attr('id', 'textarea_'+(new Date()).getTime()); @@ -56,9 +59,10 @@ $(function(){ /* In IE8 wysihtml5 iframe stays on the same line with buttons toolbar (inside popover). - Not pretty but working solution is to add
. If you fine better way, please send PR. + The only solution I found is to add
. If you fine better way, please send PR. */ - if($.browser.msie && parseInt($.browser.version, 10) <= 8) { + msieOld = /msie\s*(8|7|6)/.test(navigator.userAgent.toLowerCase()); + if(msieOld) { this.$input.before('

'); } diff --git a/src/inputs/abstract.js b/src/inputs/abstract.js index 54245bf..c1ad480 100644 --- a/src/inputs/abstract.js +++ b/src/inputs/abstract.js @@ -159,7 +159,7 @@ To create your own input you can inherit from this class. }, setAttr: function(attr) { - if (this.options[attr]) { + if (this.options[attr] !== undefined && this.options[attr] !== null) { this.$input.attr(attr, this.options[attr]); } }, @@ -186,7 +186,10 @@ To create your own input you can inherit from this class. @type string @default input-medium **/ - inputclass: 'input-medium' + inputclass: 'input-medium', + //scope for external methods (e.g. source defined as function) + //for internal use only + scope: null }; $.extend($.fn.editabletypes, {abstractinput: AbstractInput}); diff --git a/src/inputs/checklist.js b/src/inputs/checklist.js index 320b02c..4a194b6 100644 --- a/src/inputs/checklist.js +++ b/src/inputs/checklist.js @@ -16,7 +16,6 @@ $(function(){ {value: 2, text: 'option2'}, {value: 3, text: 'option3'} ] - } }); }); diff --git a/src/inputs/combodate/combodate.js b/src/inputs/combodate/combodate.js index dd835de..e6b4863 100644 --- a/src/inputs/combodate/combodate.js +++ b/src/inputs/combodate/combodate.js @@ -1,6 +1,6 @@ /** Combodate input - dropdown date and time picker. -Based on [combodate](http://vitalets.github.com/combodate) plugin. To use it you should manually include [momentjs](http://momentjs.com). +Based on [combodate](http://vitalets.github.com/combodate) plugin (included). To use it you should manually include [momentjs](http://momentjs.com). @@ -48,6 +48,9 @@ $(function(){ this.options.viewformat = this.options.format; } + //try parse combodate config defined as json string in data-combodate + options.combodate = $.fn.editableutils.tryParseJson(options.combodate, true); + //overriding combodate config (as by default jQuery extend() is not recursive) this.options.combodate = $.extend({}, Constructor.defaults.combodate, options.combodate, { format: this.options.format, diff --git a/src/inputs/combodate/lib/combodate.js b/src/inputs/combodate/lib/combodate.js index a22203e..c9a7d6c 100644 --- a/src/inputs/combodate/lib/combodate.js +++ b/src/inputs/combodate/lib/combodate.js @@ -1,5 +1,5 @@ /** -* Combodate - 1.0.1 +* Combodate - 1.0.2 * Dropdown date and time picker. * Converts text input into dropdowns to pick day, month, year, hour, minute and second. * Uses momentjs as datetime library http://momentjs.com. @@ -102,9 +102,13 @@ Initialize items of combos. Handles `firstItem` option */ initItems: function(key) { - var values = []; + var values = [], + relTime; + if(this.options.firstItem === 'name') { - var header = typeof moment.relativeTime[key] === 'function' ? moment.relativeTime[key](1, true, key, false) : moment.relativeTime[key]; + //need both to suuport moment ver < 2 and >= 2 + relTime = moment.relativeTime || moment.langData()._relativeTime; + var header = typeof relTime[key] === 'function' ? relTime[key](1, true, key, false) : relTime[key]; //take last entry (see momentjs lang files structure) header = header.split(' ').reverse()[0]; values.push(['', header]); @@ -150,9 +154,9 @@ for(i=0; i<=11; i++) { if(longNames) { - name = moment.months[i]; + name = moment().month(i).format('MMMM'); } else if(shortNames) { - name = moment.monthsShort[i]; + name = moment().month(i).format('MMM'); } else if(twoDigit) { name = this.leadZero(i+1); } else { diff --git a/src/inputs/combodate/lib/moment.min.1.7.2.js b/src/inputs/combodate/lib/moment.min.1.7.2.js new file mode 100644 index 0000000..67cb152 --- /dev/null +++ b/src/inputs/combodate/lib/moment.min.1.7.2.js @@ -0,0 +1,6 @@ +// moment.js +// version : 1.7.2 +// author : Tim Wood +// license : MIT +// momentjs.com +(function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~t;break;case"a":case"A":n._isPm=(t+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":s[3]=~~t;break;case"m":case"mm":s[4]=~~t;break;case"s":case"ss":s[5]=~~t;break;case"S":case"SS":case"SSS":s[6]=~~(("0."+t)*1e3);break;case"X":n._d=new Date(parseFloat(t)*1e3);break;case"Z":case"ZZ":n._useUTC=!0,r=(t+"").match(x),r&&r[1]&&(n._tzh=~~r[1]),r&&r[2]&&(n._tzm=~~r[2]),r&&r[0]==="+"&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}t==null&&(n._isValid=!1)}function J(e){var t,n,r=[];if(e._d)return;for(t=0;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];r[3]+=e._tzh||0,r[4]+=e._tzm||0,n=new Date(0),e._useUTC?(n.setUTCFullYear(r[0],r[1],r[2]),n.setUTCHours(r[3],r[4],r[5],r[6])):(n.setFullYear(r[0],r[1],r[2]),n.setHours(r[3],r[4],r[5],r[6])),e._d=n}function K(e){var t=e._f.match(a),n=e._i,r,i;e._a=[];for(r=0;r0,f[4]=n,Z.apply({},f)}function tt(e,n,r){var i=r-n,s=r-e.day();return s>i&&(s-=7),s11?n?"pm":"PM":n?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(e,t){var n=this._calendar[e];return typeof n=="function"?n.apply(t):n},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(e,t,n,r){var i=this._relativeTime[n];return typeof i=="function"?i(e,t,n,r):i.replace(/%d/i,e)},pastFuture:function(e,t){var n=this._relativeTime[e>0?"future":"past"];return typeof n=="function"?n(t):n.replace(/%s/i,t)},ordinal:function(e){return this._ordinal.replace("%d",e)},_ordinal:"%d",preparse:function(e){return e},postformat:function(e){return e},week:function(e){return tt(e,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},t=function(e,t,n){return nt({_i:e,_f:t,_l:n,_isUTC:!1})},t.utc=function(e,t,n){return nt({_useUTC:!0,_isUTC:!0,_l:n,_i:e,_f:t})},t.unix=function(e){return t(e*1e3)},t.duration=function(e,n){var r=t.isDuration(e),i=typeof e=="number",s=r?e._data:i?{}:e,o;return i&&(n?s[n]=e:s.milliseconds=e),o=new P(s),r&&e.hasOwnProperty("_lang")&&(o._lang=e._lang),o},t.version=n,t.defaultFormat=E,t.lang=function(e,n){var r;if(!e)return t.fn._lang._abbr;n?R(e,n):s[e]||U(e),t.duration.fn._lang=t.fn._lang=U(e)},t.langData=function(e){return e&&e._lang&&e._lang._abbr&&(e=e._lang._abbr),U(e)},t.isMoment=function(e){return e instanceof D},t.isDuration=function(e){return e instanceof P},t.fn=D.prototype={clone:function(){return t(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return t.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var e=this;return[e.year(),e.month(),e.date(),e.hours(),e.minutes(),e.seconds(),e.milliseconds()]},isValid:function(){return this._isValid==null&&(this._a?this._isValid=!q(this._a,(this._isUTC?t.utc(this._a):t(this._a)).toArray()):this._isValid=!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(e){var n=X(this,e||t.defaultFormat);return this.lang().postformat(n)},add:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,1),this},subtract:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,-1),this},diff:function(e,n,r){var i=this._isUTC?t(e).utc():t(e).local(),s=(this.zone()-i.zone())*6e4,o,u;return n&&(n=n.replace(/s$/,"")),n==="year"||n==="month"?(o=(this.daysInMonth()+i.daysInMonth())*432e5,u=(this.year()-i.year())*12+(this.month()-i.month()),u+=(this-t(this).startOf("month")-(i-t(i).startOf("month")))/o,n==="year"&&(u/=12)):(o=this-i-s,u=n==="second"?o/1e3:n==="minute"?o/6e4:n==="hour"?o/36e5:n==="day"?o/864e5:n==="week"?o/6048e5:o),r?u:B(u)},from:function(e,n){return t.duration(this.diff(e)).lang(this.lang()._abbr).humanize(!n)},fromNow:function(e){return this.from(t(),e)},calendar:function(){var e=this.diff(t().startOf("day"),"days",!0),n=e<-6?"sameElse":e<-1?"lastWeek":e<0?"lastDay":e<1?"sameDay":e<2?"nextDay":e<7?"nextWeek":"sameElse";return this.format(this.lang().calendar(n,this))},isLeapYear:function(){var e=this.year();return e%4===0&&e%100!==0||e%400===0},isDST:function(){return this.zone()+t(e).startOf(n)},isBefore:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)<+t(e).startOf(n)},isSame:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)===+t(e).startOf(n)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return t.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(e){var n=r((t(this).startOf("day")-t(this).startOf("year"))/864e5)+1;return e==null?n:this.add("d",e-n)},isoWeek:function(e){var t=tt(this,1,4);return e==null?t:this.add("d",(e-t)*7)},week:function(e){var t=this.lang().week(this);return e==null?t:this.add("d",(e-t)*7)},lang:function(t){return t===e?this._lang:(this._lang=U(t),this)}};for(i=0;i this.endDate) { @@ -326,19 +356,17 @@ } else { this.viewDate = new Date(this.date); } - - if (oldViewDate && oldViewDate.getTime() != this.viewDate.getTime()){ - this.element.trigger({ - type: 'changeDate', - date: this.viewDate - }); - } this.fill(); }, fillDow: function(){ var dowCnt = this.weekStart, html = ''; + if(this.calendarWeeks){ + var cell = ' '; + html += cell; + this.picker.find('.datepicker-days thead tr:first-child').prepend(cell); + } while (dowCnt < this.weekStart + 7) { html += ''+dates[this.language].daysMin[(dowCnt++)%7]+''; } @@ -365,7 +393,7 @@ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, currentDate = this.date && this.date.valueOf(), today = new Date(); - this.picker.find('.datepicker-days thead th:eq(1)') + this.picker.find('.datepicker-days thead th.switch') .text(dates[this.language].months[month]+' '+year); this.picker.find('tfoot th.today') .text(dates[this.language].today) @@ -384,6 +412,21 @@ while(prevMonth.valueOf() < nextMonth) { if (prevMonth.getUTCDay() == this.weekStart) { html.push(''); + if(this.calendarWeeks){ + // ISO 8601: First week contains first thursday. + // ISO also states week starts on Monday, but we can be more abstract here. + var + // Start of current week: based on weekstart/current date + ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), + // Thursday of this week + th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), + // First Thursday of year, year from thursday + yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5), + // Calendar week: ms between thursdays, div ms per day, div 7 days + calWeek = (th - yth) / 864e5 / 7 + 1; + html.push(''+ calWeek +''); + + } } clsName = ''; if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { @@ -519,19 +562,29 @@ if (!target.is('.disabled')) { this.viewDate.setUTCDate(1); if (target.is('.month')) { + var day = 1; var month = target.parent().find('span').index(target); + var year = this.viewDate.getUTCFullYear(); this.viewDate.setUTCMonth(month); this.element.trigger({ type: 'changeMonth', date: this.viewDate }); + if ( this.minViewMode == 1 ) { + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } } else { var year = parseInt(target.text(), 10)||0; + var day = 1; + var month = 0; this.viewDate.setUTCFullYear(year); this.element.trigger({ type: 'changeYear', date: this.viewDate }); + if ( this.minViewMode == 2 ) { + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } } this.showMode(-1); this.fill(); @@ -728,7 +781,7 @@ showMode: function(dir) { if (dir) { - this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir)); + this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir)); } /* vitalets: fixing bug of very special conditions: diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js index 1d233ef..b7b57a3 100644 --- a/src/inputs/date/date.js +++ b/src/inputs/date/date.js @@ -111,12 +111,24 @@ $(function(){ }, autosubmit: function() { + this.$input.on('mouseup', '.day', function(e){ + if($(e.currentTarget).is('.old') || $(e.currentTarget).is('.new')) { + return; + } + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + //changedate is not suitable as it triggered when showing datepicker. see #149 + /* this.$input.on('changeDate', function(e){ var $form = $(this).closest('form'); setTimeout(function() { $form.submit(); }, 200); }); + */ } }); @@ -159,12 +171,14 @@ $(function(){ @default { weekStart: 0, startView: 0, + minViewMode: 0, autoclose: false } **/ datepicker:{ weekStart: 0, startView: 0, + minViewMode: 0, autoclose: false }, /** diff --git a/src/inputs/date/datefield.js b/src/inputs/date/datefield.js index 0919de4..de9e5f0 100644 --- a/src/inputs/date/datefield.js +++ b/src/inputs/date/datefield.js @@ -69,6 +69,7 @@ Automatically shown in inline mode. datepicker: { weekStart: 0, startView: 0, + minViewMode: 0, autoclose: true } }); diff --git a/src/inputs/list.js b/src/inputs/list.js index e5fcb00..d01de0b 100644 --- a/src/inputs/list.js +++ b/src/inputs/list.js @@ -70,12 +70,19 @@ List - abstract class for inputs that have source option loaded from js array or error.call(this); return; } + + var source = this.options.source; + + //run source if it function + if ($.isFunction(source)) { + source = source.call(this.options.scope); + } //loading from url - if (typeof this.options.source === 'string') { + if (typeof source === 'string') { //try to get from cache if(this.options.sourceCache) { - var cacheID = this.options.source, + var cacheID = source, cache; if (!$(document).data(cacheID)) { @@ -108,7 +115,7 @@ List - abstract class for inputs that have source option loaded from js array or //loading sourceData from server $.ajax({ - url: this.options.source, + url: source, type: 'get', cache: false, dataType: 'json', @@ -143,12 +150,8 @@ List - abstract class for inputs that have source option loaded from js array or } }, this) }); - } else { //options as json/array/function - if ($.isFunction(this.options.source)) { - this.sourceData = this.makeArray(this.options.source()); - } else { - this.sourceData = this.makeArray(this.options.source); - } + } else { //options as json/array + this.sourceData = this.makeArray(source); if($.isArray(this.sourceData)) { this.doPrepend(); @@ -165,16 +168,20 @@ List - abstract class for inputs that have source option loaded from js array or } if(!$.isArray(this.prependData)) { + //run prepend if it is function (once) + if ($.isFunction(this.options.prepend)) { + this.options.prepend = this.options.prepend.call(this.options.scope); + } + //try parse json in single quotes this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true); + + //convert prepend from string to object if (typeof this.options.prepend === 'string') { this.options.prepend = {'': this.options.prepend}; - } - if (typeof this.options.prepend === 'function') { - this.prependData = this.makeArray(this.options.prepend()); - } else { - this.prependData = this.makeArray(this.options.prepend); } + + this.prependData = this.makeArray(this.options.prepend); } if($.isArray(this.prependData) && $.isArray(this.sourceData)) { diff --git a/src/inputs/select.js b/src/inputs/select.js index 0a0b4a7..18f0d25 100644 --- a/src/inputs/select.js +++ b/src/inputs/select.js @@ -15,7 +15,6 @@ $(function(){ {value: 2, text: 'Blocked'}, {value: 3, text: 'Deleted'} ] - } }); }); @@ -85,4 +84,4 @@ $(function(){ $.fn.editabletypes.select = Select; -}(window.jQuery)); \ No newline at end of file +}(window.jQuery)); diff --git a/src/inputs/select2/select2.js b/src/inputs/select2/select2.js index fb1a103..70e503f 100644 --- a/src/inputs/select2/select2.js +++ b/src/inputs/select2/select2.js @@ -6,6 +6,9 @@ You should manually include select2 distributive: +**Note:** currently `ajax` source for select2 is not supported, as it's not possible to load it in closed select2 state. +The solution is to load source manually and assign statically. + @class select2 @extends abstractinput @since 1.4.1 @@ -35,14 +38,14 @@ $(function(){ options.select2 = options.select2 || {}; var that = this, - mixin = { + mixin = { //mixin to select2 options placeholder: options.placeholder }; //detect whether it is multi-valued this.isMultiple = options.select2.tags || options.select2.multiple; - //if not `tags` mode, we need define init set data from source + //if not `tags` mode, we need define initSelection to set data from source if(!options.select2.tags) { if(options.source) { mixin.data = options.source; @@ -50,6 +53,23 @@ $(function(){ //this function can be defaulted in seletc2. See https://github.com/ivaynberg/select2/issues/710 mixin.initSelection = function (element, callback) { + //temp: try update results + /* + if(options.select2 && options.select2.ajax) { + console.log('attached'); + var original = $(element).data('select2').postprocessResults; + console.log(original); + $(element).data('select2').postprocessResults = function(data, initial) { + console.log('postprocess'); + // this.element.triggerHandler('loaded', [data]); + original.apply(this, arguments); + } + + // $(element).on('loaded', function(){console.log('loaded');}); + $(element).data('select2').updateResults(true); + } + */ + var val = that.str2value(element.val()), data = $.fn.editableutils.itemsByValue(val, mixin.data, 'id'); @@ -74,18 +94,30 @@ $(function(){ //apply select2 this.$input.select2(this.options.select2); + //when data is loaded via ajax, we need to know when it's done + if('ajax' in this.options.select2) { + /* + console.log('attached'); + var original = this.$input.data('select2').postprocessResults; + this.$input.data('select2').postprocessResults = function(data, initial) { + this.element.triggerHandler('loaded', [data]); + original.apply(this, arguments); + } + */ + } + + //trigger resize of editableform to re-position container in multi-valued mode if(this.isMultiple) { this.$input.on('change', function() { $(this).closest('form').parent().triggerHandler('resize'); }); - } - - }, + } + }, value2html: function(value, element) { var text = '', data; - if(this.$input) { //when submitting form + if(this.$input) { //called when submitting form and select2 already exists data = this.$input.select2('data'); } else { //on init (autotext) //here select2 instance not created yet and data may be even not loaded. @@ -94,6 +126,8 @@ $(function(){ data = value; } else if(this.options.select2.data) { data = $.fn.editableutils.itemsByValue(value, this.options.select2.data, 'id'); + } else { + //if('ajax' in this.options.select2) { } } @@ -117,7 +151,7 @@ $(function(){ }, value2input: function(value) { - this.$input.val(value).trigger('change'); + this.$input.val(value).trigger('change', true); //second argument needed to separate initial change from user's click (for autosubmit) }, input2value: function() { @@ -142,7 +176,15 @@ $(function(){ } return val; - } + }, + + autosubmit: function() { + this.$input.on('change', function(e, isInitial){ + if(!isInitial) { + $(this).closest('form').submit(); + } + }); + } }); diff --git a/src/inputs/text.js b/src/inputs/text.js index b41d717..df5dd5a 100644 --- a/src/inputs/text.js +++ b/src/inputs/text.js @@ -44,8 +44,20 @@ $(function(){ if (this.options.clear) { this.$clear = $(''); this.$input.after(this.$clear) - .css('padding-right', 20) - .keyup($.proxy(this.toggleClear, this)) + .css('padding-right', 24) + .keyup($.proxy(function(e) { + //arrows, enter, tab, etc + if(~$.inArray(e.keyCode, [40,38,9,13,27])) { + return; + } + + clearTimeout(this.t); + var that = this; + this.t = setTimeout(function() { + that.toggleClear(e); + }, 100); + + }, this)) .parent().css('position', 'relative'); this.$clear.click($.proxy(this.clear, this)); @@ -63,19 +75,24 @@ $(function(){ delta = 3; } - this.$clear.css({top: delta, right: delta}); + this.$clear.css({bottom: delta, right: delta}); } }, //show / hide clear button - toggleClear: function() { + toggleClear: function(e) { if(!this.$clear) { return; } - if(this.$input.val().length) { + var len = this.$input.val().length, + visible = this.$clear.is(':visible'); + + if(len && !visible) { this.$clear.show(); - } else { + } + + if(!len && visible) { this.$clear.hide(); } }, diff --git a/src/inputs/typeahead.js b/src/inputs/typeahead.js index 8945059..8f1ba36 100644 --- a/src/inputs/typeahead.js +++ b/src/inputs/typeahead.js @@ -25,7 +25,6 @@ $(function(){ {value: 'us', text: 'United States'}, {value: 'ru', text: 'Russia'} ] - } }); }); @@ -57,8 +56,11 @@ $(function(){ //apply typeahead this.$input.typeahead(this.options.typeahead); - //attach own render method - this.$input.data('typeahead').render = $.proxy(this.typeaheadRender, this.$input.data('typeahead')); + //patch some methods in typeahead + var ta = this.$input.data('typeahead'); + ta.render = $.proxy(this.typeaheadRender, ta); + ta.select = $.proxy(this.typeaheadSelect, ta); + ta.move = $.proxy(this.typeaheadMove, ta); this.renderClear(); this.setClass(); @@ -137,7 +139,7 @@ $(function(){ /* Typeahead option methods used as defaults */ - /*jshint eqeqeq:false, curly: false, laxcomma: true*/ + /*jshint eqeqeq:false, curly: false, laxcomma: true, asi: true*/ matcher: function (item) { return $.fn.typeahead.Constructor.prototype.matcher.call(this, item.text); }, @@ -161,7 +163,6 @@ $(function(){ return $.fn.typeahead.Constructor.prototype.highlighter.call(this, item.text); }, updater: function (item) { - item = this.$menu.find('.active').data('item'); this.$element.data('value', item.value); return item.text; }, @@ -172,7 +173,7 @@ $(function(){ There are a lot of disscussion in bootstrap repo on this point and still no result. See https://github.com/twitter/bootstrap/issues/5967 - This function just store item in via jQuery data() method instead of attr('data-value') + This function just store item via jQuery data() method instead of attr('data-value') */ typeaheadRender: function (items) { var that = this; @@ -184,11 +185,57 @@ $(function(){ return i[0]; }); - items.first().addClass('active'); + //add option to disable autoselect of first line + //see https://github.com/twitter/bootstrap/pull/4164 + if (this.options.autoSelect) { + items.first().addClass('active'); + } this.$menu.html(items); return this; + }, + + //add option to disable autoselect of first line + //see https://github.com/twitter/bootstrap/pull/4164 + typeaheadSelect: function () { + var val = this.$menu.find('.active').data('item') + if(this.options.autoSelect || val){ + this.$element + .val(this.updater(val)) + .change() + } + return this.hide() + }, + + /* + if autoSelect = false and nothing matched we need extra press onEnter that is not convinient. + This patch fixes it. + */ + typeaheadMove: function (e) { + if (!this.shown) return + + switch(e.keyCode) { + case 9: // tab + case 13: // enter + case 27: // escape + if (!this.$menu.find('.active').length) return + e.preventDefault() + break + + case 38: // up arrow + e.preventDefault() + this.prev() + break + + case 40: // down arrow + e.preventDefault() + this.next() + break + } + + e.stopPropagation() } - /*jshint eqeqeq: true, curly: true, laxcomma: false*/ + + /*jshint eqeqeq: true, curly: true, laxcomma: false, asi: false*/ }); diff --git a/test/libs/jquery/jquery-1.9.0.min.js b/test/libs/jquery/jquery-1.9.0.min.js new file mode 100644 index 0000000..50d1b22 --- /dev/null +++ b/test/libs/jquery/jquery-1.9.0.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("