app/assets/javascripts/bootstrap-editable.js in bootstrap-x-editable-rails-1.4.6.1 vs app/assets/javascripts/bootstrap-editable.js in bootstrap-x-editable-rails-1.5.0
- old
+ new
@@ -1,10 +1,9 @@
-/*! X-editable - v1.4.6
+/*! X-editable - v1.5.0
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
* http://github.com/vitalets/x-editable
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
-
/**
Form with single input element, two buttons and two states: normal/loading.
Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
Editableform is linked with one of input types, e.g. 'text', 'select' etc.
@@ -31,10 +30,13 @@
this.input = this.options.input;
//set initial value
//todo: may be add check: typeof str === 'string' ?
this.value = this.input.str2value(this.options.value);
+
+ //prerender: get input.$input
+ this.input.prerender();
},
initTemplate: function() {
this.$form = $($.fn.editableform.template);
},
initButtons: function() {
@@ -78,13 +80,12 @@
//init input
this.initInput();
//append input to form
- this.input.prerender();
this.$form.find('div.editable-input').append(this.input.$tpl);
-
+
//append form to container
this.$div.append(this.$form);
//render input
$.when(this.input.render())
@@ -618,10 +619,13 @@
//error class attached to control-group
$.fn.editableform.errorGroupClass = null;
//error class attached to editable-error-block
$.fn.editableform.errorBlockClass = 'editable-error';
+
+ //engine
+ $.fn.editableform.engine = 'jquery';
}(window.jQuery));
/**
* EditableForm utilites
*/
@@ -896,10 +900,12 @@
Popup.prototype = {
containerName: null, //method to call container on element
containerDataName: null, //object name in element's .data()
innerCss: null, //tbd in child class
containerClass: 'editable-container editable-popup', //css class applied to container element
+ defaults: {}, //container itself defaults
+
init: function(element, options) {
this.$element = $(element);
//since 1.4.1 container do not use data-* directly as they already merged into options.
this.options = $.extend({}, $.fn.editableContainer.defaults, options);
this.splitOptions();
@@ -973,14 +979,13 @@
if(!$.fn[this.containerName]) {
throw new Error(this.containerName + ' not found. Have you included corresponding js file?');
}
- var cDef = $.fn[this.containerName].defaults;
//keys defined in container defaults go to container, others go to form
for(var k in this.options) {
- if(k in cDef) {
+ if(k in this.defaults) {
this.containerOptions[k] = this.options[k];
} else {
this.formOptions[k] = this.options[k];
}
}
@@ -1725,17 +1730,16 @@
*/
if(isEmpty !== undefined) {
this.isEmpty = isEmpty;
} else {
//detect empty
- if($.trim(this.$element.html()) === '') {
- this.isEmpty = true;
- } else if($.trim(this.$element.text()) !== '') {
- this.isEmpty = false;
+ //for some inputs we need more smart check
+ //e.g. wysihtml5 may have <br>, <p></p>, <img>
+ if(typeof(this.input.isEmpty) === 'function') {
+ this.isEmpty = this.input.isEmpty(this.$element);
} else {
- //e.g. '<img>'
- this.isEmpty = !this.$element.height() || !this.$element.width();
+ this.isEmpty = $.trim(this.$element.html()) === '';
}
}
//emptytext shown only for enabled
if(!this.options.disabled) {
@@ -2247,11 +2251,11 @@
@property highlight
@type string|boolean
@since 1.4.5
@default #FFFF80
**/
- highlight: '#FFFF80'
+ highlight: '#FFFF80'
};
}(window.jQuery));
/**
@@ -2306,11 +2310,11 @@
@method value2html(value, element)
@param {mixed} value
@param {DOMElement} element
**/
value2html: function(value, element) {
- $(element).text($.trim(value));
+ $(element)[this.options.escape ? 'text' : 'html']($.trim(value));
},
/**
Converts element's html to value
@@ -2413,11 +2417,11 @@
**/
destroy: function() {
},
// -------- helper functions --------
- setClass: function() {
+ setClass: function() {
if(this.options.inputclass) {
this.$input.addClass(this.options.inputclass);
}
},
@@ -2445,13 +2449,26 @@
/**
CSS class automatically applied to input
@property inputclass
@type string
- @default input-medium
+ @default null
**/
- inputclass: 'input-medium',
+ inputclass: null,
+
+ /**
+ If `true` - html will be escaped in content of element via $.text() method.
+ If `false` - html will not be escaped, $.html() used.
+ When you use own `display` function, this option obviosly has no effect.
+
+ @property escape
+ @type boolean
+ @since 1.5.0
+ @default true
+ **/
+ escape: true,
+
//scope for external methods (e.g. source defined as function)
//for internal use only
scope: null,
//need to re-declare showbuttons here to get it's value from common config (passed only options existing in defaults)
@@ -2579,12 +2596,12 @@
cache.callbacks = [];
cache.err_callbacks = [];
}
}
- //loading sourceData from server
- $.ajax({
+ //ajaxOptions for source. Can be overwritten bt options.sourceOptions
+ var ajaxOptions = $.extend({
url: source,
type: 'get',
cache: false,
dataType: 'json',
success: $.proxy(function (data) {
@@ -2615,11 +2632,15 @@
cache.loading = false;
//run error callbacks for other fields
$.each(cache.err_callbacks, function () { this.call(); });
}
}, this)
- });
+ }, this.options.sourceOptions);
+
+ //loading sourceData from server
+ $.ajax(ajaxOptions);
+
} else { //options as json/array
this.sourceData = this.makeArray(source);
if($.isArray(this.sourceData)) {
this.doPrepend();
@@ -2775,11 +2796,21 @@
@property sourceCache
@type boolean
@default true
@since 1.2.0
**/
- sourceCache: true
+ sourceCache: true,
+ /**
+ Additional ajax options to be used in $.ajax() when loading list from server.
+ Useful to send extra parameters (`data` key) or change request method (`type` key).
+
+ @property sourceOptions
+ @type object|function
+ @default null
+ @since 1.5.0
+ **/
+ sourceOptions: null
});
$.fn.editabletypes.list = List;
}(window.jQuery));
@@ -3036,11 +3067,11 @@
@class select
@extends list
@final
@example
-<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a>
+<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-title="Select status"></a>
<script>
$(function(){
$('#status').editable({
value: 2,
source: [
@@ -3103,11 +3134,12 @@
if(items.length) {
text = items[0].text;
}
- $(element).text(text);
+ //$(element).text(text);
+ $.fn.editabletypes.abstractinput.prototype.value2html.call(this, text, element);
},
autosubmit: function() {
this.$input.off('keydown.editable').on('change.editable', function(){
$(this).closest('form').submit();
@@ -3133,11 +3165,11 @@
@class checklist
@extends list
@final
@example
-<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-original-title="Select options"></a>
+<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-title="Select options"></a>
<script>
$(function(){
$('#options').editable({
value: [2, 3],
source: [
@@ -3227,14 +3259,18 @@
},
//collect text of checked boxes
value2htmlFinal: function(value, element) {
var html = [],
- checked = $.fn.editableutils.itemsByValue(value, this.sourceData);
+ checked = $.fn.editableutils.itemsByValue(value, this.sourceData),
+ escape = this.options.escape;
if(checked.length) {
- $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
+ $.each(checked, function(i, v) {
+ var text = escape ? $.fn.editableutils.escape(v.text) : v.text;
+ html.push(text);
+ });
$(element).html(html.join('<br>'));
} else {
$(element).empty();
}
},
@@ -3500,11 +3536,11 @@
}(window.jQuery));
/**
Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options.
-Compatible **select2 version is 3.4.1**!
+
You should manually download and include select2 distributive:
<link href="select2/select2.css" rel="stylesheet" type="text/css"></link>
<script src="select2/select2.js"></script>
@@ -3641,14 +3677,16 @@
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
$.extend(Constructor.prototype, {
render: function() {
this.setClass();
-
- //apply select2
- this.$input.select2(this.options.select2);
+ //can not apply select2 here as it calls initSelection
+ //over input that does not have correct value yet.
+ //apply select2 only in value2input
+ //this.$input.select2(this.options.select2);
+
//when data is loaded via ajax, we need to know when it's done to populate listData
if(this.isRemote) {
//listen to loaded event to populate data
this.$input.on('select2-loaded', $.proxy(function(e) {
this.sourceData = e.items.results;
@@ -3671,11 +3709,12 @@
data = value;
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
} else if(this.sourceData) {
data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
} else {
- //can not get list of possible values (e.g. autotext for select2 with ajax source)
+ //can not get list of possible values
+ //(e.g. autotext for select2 with ajax source)
}
//data may be array (when multiple values allowed)
if($.isArray(data)) {
//collect selected data and show with separator
@@ -3687,11 +3726,12 @@
text = that.formatSelection(data);
}
text = $.isArray(text) ? text.join(this.options.viewseparator) : text;
- $(element).text(text);
+ //$(element).text(text);
+ Constructor.superclass.value2html.call(this, text, element);
},
html2value: function(html) {
return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null;
},
@@ -3706,20 +3746,26 @@
return;
}
}
*/
- //for remote source just set value, text is updated by initSelection
- this.$input.val(value).trigger('change', true); //second argument needed to separate initial change from user's click (for autosubmit)
+ //for remote source just set value, text is updated by initSelection
+ if(!this.$input.data('select2')) {
+ this.$input.val(value);
+ this.$input.select2(this.options.select2);
+ } else {
+ //second argument needed to separate initial change from user's click (for autosubmit)
+ this.$input.val(value).trigger('change', true);
+ }
//if remote source AND no user's initSelection provided --> try to use element's text
if(this.isRemote && !this.isMultiple && !this.options.select2.initSelection) {
var customId = this.options.select2.id,
customText = this.options.select2.formatSelection;
if(!customId && !customText) {
var data = {id: value, text: $(this.options.scope).text()};
- this.$input.select2('data', data);
+ this.$input.select2('data', data);
}
}
},
input2value: function() {
@@ -3804,22 +3850,22 @@
Source data for select. It will be assigned to select2 `data` property and kept here just for convenience.
Please note, that format is different from simple `select` input: use 'id' instead of 'value'.
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
@property source
- @type array
+ @type array|string|function
@default null
**/
source: null,
/**
Separator used to display tags.
@property viewseparator
@type string
@default ', '
**/
- viewseparator: ', '
+ viewseparator: ', '
});
$.fn.editabletypes.select2 = Constructor;
}(window.jQuery));
@@ -4295,11 +4341,11 @@
@class combodate
@extends abstractinput
@final
@since 1.4.0
@example
-<a href="#" id="dob" data-type="combodate" data-pk="1" data-url="/post" data-value="1984-05-15" data-original-title="Select date"></a>
+<a href="#" id="dob" data-type="combodate" data-pk="1" data-url="/post" data-value="1984-05-15" data-title="Select date"></a>
<script>
$(function(){
$('#dob').editable({
format: 'YYYY-MM-DD',
viewformat: 'DD.MM.YYYY',
@@ -4341,11 +4387,18 @@
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
$.extend(Constructor.prototype, {
render: function () {
this.$input.combodate(this.options.combodate);
+
+ if($.fn.editableform.engine === 'bs3') {
+ this.$input.siblings().find('select').addClass('form-control');
+ }
+ if(this.options.inputclass) {
+ this.$input.siblings().find('select').addClass(this.options.inputclass);
+ }
//"clear" link
/*
if(this.options.clear) {
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
e.preventDefault();
@@ -4358,11 +4411,12 @@
*/
},
value2html: function(value, element) {
var text = value ? value.format(this.options.viewformat) : '';
- $(element).text(text);
+ //$(element).text(text);
+ Constructor.superclass.value2html.call(this, text, element);
},
html2value: function(html) {
return html ? moment(html, this.options.viewformat) : null;
},
@@ -4466,29 +4520,49 @@
$.fn.editabletypes.combodate = Constructor;
}(window.jQuery));
/*
-Editableform based on Twitter Bootstrap
+Editableform based on Twitter Bootstrap 2
*/
(function ($) {
"use strict";
+ //store parent methods
+ var pInitInput = $.fn.editableform.Constructor.prototype.initInput;
+
$.extend($.fn.editableform.Constructor.prototype, {
initTemplate: function() {
this.$form = $($.fn.editableform.template);
this.$form.find('.editable-error-block').addClass('help-block');
+ },
+ initInput: function() {
+ pInitInput.apply(this);
+
+ //for bs2 set default class `input-medium` to standard inputs
+ var emptyInputClass = this.input.options.inputclass === null || this.input.options.inputclass === false;
+ var defaultClass = 'input-medium';
+
+ //add bs2 default class to standard inputs
+ //if(this.input.$input.is('input,select,textarea')) {
+ var stdtypes = 'text,select,textarea,password,email,url,tel,number,range,time'.split(',');
+ if(~$.inArray(this.input.type, stdtypes) && emptyInputClass) {
+ this.input.options.inputclass = defaultClass;
+ this.input.$input.addClass(defaultClass);
+ }
}
});
//buttons
$.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+
'<button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>';
//error classes
$.fn.editableform.errorGroupClass = 'error';
- $.fn.editableform.errorBlockClass = null;
+ $.fn.editableform.errorBlockClass = null;
+ //engine
+ $.fn.editableform.engine = 'bs2';
}(window.jQuery));
/**
* Editable Popover
* ---------------------
@@ -4500,17 +4574,18 @@
//extend methods
$.extend($.fn.editableContainer.Popup.prototype, {
containerName: 'popover',
//for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content)
innerCss: $.fn.popover && $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content',
-
+ defaults: $.fn.popover.defaults,
+
initContainer: function(){
$.extend(this.containerOptions, {
trigger: 'manual',
selector: false,
content: ' ',
- template: $.fn.popover.defaults.template
+ template: this.defaults.template
});
//as template property is used in inputs, hide it from popover
var t;
if(this.$element.data('template')) {
@@ -5933,11 +6008,11 @@
@class date
@extends abstractinput
@final
@example
-<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
+<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-title="Select date">15/05/1984</a>
<script>
$(function(){
$('#dob').editable({
format: 'yyyy-mm-dd',
viewformat: 'dd/mm/yyyy',
@@ -6009,11 +6084,11 @@
}
},
value2html: function(value, element) {
var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : '';
- Date.superclass.value2html(text, element);
+ Date.superclass.value2html.call(this, text, element);
},
html2value: function(html) {
return this.parseDate(html, this.parsedViewFormat);
},
@@ -6331,11 +6406,11 @@
value2html: function(value, element) {
//formatDate works with UTCDate!
var text = value ? this.dpg.formatDate(this.toUTC(value), this.parsedViewFormat, this.options.datetimepicker.language, this.options.formatType) : '';
if(element) {
- DateTime.superclass.value2html(text, element);
+ DateTime.superclass.value2html.call(this, text, element);
} else {
return text;
}
},
@@ -6555,11 +6630,11 @@
$.fn.editabletypes.datetimefield = DateTimeField;
}(window.jQuery));
/**
-Typeahead input (bootstrap only). Based on Twitter Bootstrap [typeahead](http://twitter.github.com/bootstrap/javascript.html#typeahead).
+Typeahead input (bootstrap 2 only). Based on Twitter Bootstrap 2 [typeahead](http://getbootstrap.com/2.3.2/javascript.html#typeahead).
Depending on `source` format typeahead operates in two modes:
* **strings**:
When `source` defined as array of strings, e.g. `['text1', 'text2', 'text3' ...]`.
User can submit one of these strings or any text entered in input (even if it is not matching source).
@@ -6571,11 +6646,11 @@
@class typeahead
@extends list
@since 1.4.1
@final
@example
-<a href="#" id="country" data-type="typeahead" data-pk="1" data-url="/post" data-original-title="Input country"></a>
+<a href="#" id="country" data-type="typeahead" data-pk="1" data-url="/post" data-title="Input country"></a>
<script>
$(function(){
$('#country').editable({
value: 'ru',
source: [
@@ -6627,14 +6702,13 @@
},
value2htmlFinal: function(value, element) {
if(this.getIsObjects()) {
var items = $.fn.editableutils.itemsByValue(value, this.sourceData);
- $(element).text(items.length ? items[0].text : '');
- } else {
- $(element).text(value);
- }
+ value = items.length ? items[0].text : '';
+ }
+ $.fn.editabletypes.abstractinput.prototype.value2html.call(this, value, element);
},
html2value: function (html) {
return html ? html : null;
},
@@ -6803,10 +6877,10 @@
@property tpl
@default <input type="text">
**/
tpl:'<input type="text">',
/**
- Configuration of typeahead. [Full list of options](http://twitter.github.com/bootstrap/javascript.html#typeahead).
+ Configuration of typeahead. [Full list of options](http://getbootstrap.com/2.3.2/javascript.html#typeahead).
@property typeahead
@type object
@default null
**/
\ No newline at end of file