bootstrap-x-editable-rails 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# X-editable for Rails
|
1
|
+
# X-editable 1.4.1 for 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
|
|
5
|
-
The `bootstrap-x-editable-rails` gem integrates `X-editable` with
|
5
|
+
The `bootstrap-x-editable-rails` gem integrates `X-editable` with Rails asset pipeline. This gem only supports the Bootstrap part of X-editable.
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
@@ -31,3 +31,14 @@ Add to your `app/assets/javascripts/application.js`
|
|
31
31
|
Add to your `app/assets/stylesheets/application.css`
|
32
32
|
|
33
33
|
*= require bootstrap-editable
|
34
|
+
|
35
|
+
## Updating the gem
|
36
|
+
There are two rake tasks designed to ease the maintenance of this gem.
|
37
|
+
|
38
|
+
The `update` task pulls the latest X-editable code from github and places images, stylesheets and javascripts in the correct gem paths. It also changes background-image properties in the stylesheet to asset pipeline equivalents.
|
39
|
+
|
40
|
+
rake update
|
41
|
+
|
42
|
+
The `build` task is a simple wrapper for `gem build`
|
43
|
+
|
44
|
+
rake build
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
desc "Update"
|
2
|
+
task :update do
|
3
|
+
src_path = "x-editable-src"
|
4
|
+
dist_path = "#{src_path}/dist/bootstrap-editable"
|
5
|
+
|
6
|
+
system("rm -rf #{src_path}")
|
7
|
+
|
8
|
+
system("git clone https://github.com/vitalets/x-editable #{src_path}")
|
9
|
+
system("cd #{src_path} && npm install")
|
10
|
+
system("cd #{src_path} && grunt build")
|
11
|
+
|
12
|
+
system("cp #{dist_path}/img/clear.png vendor/assets/images/")
|
13
|
+
system("cp #{dist_path}/img/loading.gif vendor/assets/images/")
|
14
|
+
system("cp #{dist_path}/css/bootstrap-editable.css vendor/assets/stylesheets/bootstrap-editable.scss")
|
15
|
+
system("cp #{dist_path}/js/bootstrap-editable.js vendor/assets/javascripts/")
|
16
|
+
|
17
|
+
fixes
|
18
|
+
|
19
|
+
system("rm -rf x-editable-src")
|
20
|
+
end
|
21
|
+
|
22
|
+
def fixes
|
23
|
+
replace_string_in_file("vendor/assets/stylesheets/bootstrap-editable.scss", "url('../img/loading.gif')", "image-url('loading.gif')")
|
24
|
+
replace_string_in_file("vendor/assets/stylesheets/bootstrap-editable.scss", "url('../img/clear.png')", "image-url('clear.png')")
|
25
|
+
end
|
26
|
+
|
27
|
+
def replace_string_in_file(file, find, replace)
|
28
|
+
file_content = File.read(file)
|
29
|
+
|
30
|
+
File.open(file, "w") do |f|
|
31
|
+
f.puts file_content.gsub!(find, replace)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Build"
|
36
|
+
task "build" do
|
37
|
+
system("gem build bootstrap-x-editable-rails.gemspec")
|
38
|
+
end
|
Binary file
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! X-editable - v1.4.
|
1
|
+
/*! X-editable - v1.4.1
|
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 */
|
@@ -16,7 +16,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
16
16
|
|
17
17
|
var EditableForm = function (div, options) {
|
18
18
|
this.options = $.extend({}, $.fn.editableform.defaults, options);
|
19
|
-
this.$div = $(div); //div, containing form. Not form tag
|
19
|
+
this.$div = $(div); //div, containing form. Not form tag. Not editable-element.
|
20
20
|
if(!this.options.scope) {
|
21
21
|
this.options.scope = this;
|
22
22
|
}
|
@@ -30,6 +30,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
30
30
|
this.input = this.options.input;
|
31
31
|
|
32
32
|
//set initial value
|
33
|
+
//todo: may be add check: typeof str === 'string' ?
|
33
34
|
this.value = this.input.str2value(this.options.value);
|
34
35
|
},
|
35
36
|
initTemplate: function() {
|
@@ -232,6 +233,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
232
233
|
}
|
233
234
|
|
234
235
|
//if success callback returns object like {newValue: <something>} --> use that value instead of submitted
|
236
|
+
//it is usefull if you want to chnage value in url-function
|
235
237
|
if(res && typeof res === 'object' && res.hasOwnProperty('newValue')) {
|
236
238
|
newValue = res.newValue;
|
237
239
|
}
|
@@ -387,18 +389,25 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
387
389
|
type: 'text',
|
388
390
|
/**
|
389
391
|
Url for submit, e.g. <code>'/post'</code>
|
390
|
-
If function - it will be called instead of ajax. Function
|
392
|
+
If function - it will be called instead of ajax. Function should return deferred object to run fail/done callbacks.
|
391
393
|
|
392
394
|
@property url
|
393
395
|
@type string|function
|
394
396
|
@default null
|
395
397
|
@example
|
396
398
|
url: function(params) {
|
399
|
+
var d = new $.Deferred;
|
397
400
|
if(params.value === 'abc') {
|
398
|
-
var d = new $.Deferred;
|
399
401
|
return d.reject('error message'); //returning error via deferred object
|
400
402
|
} else {
|
401
|
-
|
403
|
+
//async saving data in js model
|
404
|
+
someModel.asyncSaveMethod({
|
405
|
+
...,
|
406
|
+
success: function(){
|
407
|
+
d.resolve();
|
408
|
+
}
|
409
|
+
});
|
410
|
+
return d.promise();
|
402
411
|
}
|
403
412
|
}
|
404
413
|
**/
|
@@ -689,21 +698,34 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
|
689
698
|
/*
|
690
699
|
returns array items from sourceData having value property equal or inArray of 'value'
|
691
700
|
*/
|
692
|
-
itemsByValue: function(value, sourceData) {
|
701
|
+
itemsByValue: function(value, sourceData, valueProp) {
|
693
702
|
if(!sourceData || value === null) {
|
694
703
|
return [];
|
695
704
|
}
|
696
705
|
|
697
|
-
|
698
|
-
if(!$.isArray(value)) {
|
699
|
-
value = [value];
|
700
|
-
}
|
706
|
+
valueProp = valueProp || 'value';
|
701
707
|
|
702
|
-
|
703
|
-
|
704
|
-
|
708
|
+
var isValArray = $.isArray(value),
|
709
|
+
result = [],
|
710
|
+
that = this;
|
711
|
+
|
712
|
+
$.each(sourceData, function(i, o) {
|
713
|
+
if(o.children) {
|
714
|
+
result = result.concat(that.itemsByValue(value, o.children));
|
715
|
+
} else {
|
716
|
+
/*jslint eqeq: true*/
|
717
|
+
if(isValArray) {
|
718
|
+
if($.grep(value, function(v){ return v == (o && typeof o === 'object' ? o[valueProp] : o); }).length) {
|
719
|
+
result.push(o);
|
720
|
+
}
|
721
|
+
} else {
|
722
|
+
if(value == (o && typeof o === 'object' ? o[valueProp] : o)) {
|
723
|
+
result.push(o);
|
724
|
+
}
|
725
|
+
}
|
726
|
+
/*jslint eqeq: false*/
|
727
|
+
}
|
705
728
|
});
|
706
|
-
/*jslint eqeq: false*/
|
707
729
|
|
708
730
|
return result;
|
709
731
|
},
|
@@ -785,8 +807,8 @@ Applied as jQuery method.
|
|
785
807
|
innerCss: null, //tbd in child class
|
786
808
|
init: function(element, options) {
|
787
809
|
this.$element = $(element);
|
788
|
-
//
|
789
|
-
this.options = $.extend({}, $.fn.editableContainer.defaults,
|
810
|
+
//since 1.4.1 container do not use data-* directly as they already merged into options.
|
811
|
+
this.options = $.extend({}, $.fn.editableContainer.defaults, options);
|
790
812
|
this.splitOptions();
|
791
813
|
|
792
814
|
//set scope of form callbacks to element
|
@@ -878,6 +900,7 @@ Applied as jQuery method.
|
|
878
900
|
cancel: $.proxy(function(){ this.hide('cancel'); }, this), //click on calcel button
|
879
901
|
show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state)
|
880
902
|
rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown
|
903
|
+
resize: $.proxy(this.setPosition, this), //this allows to re-position container when form size is changed
|
881
904
|
rendered: $.proxy(function(){
|
882
905
|
/**
|
883
906
|
Fired when container is shown and form is rendered (for select will wait for loading dropdown options)
|
@@ -1004,7 +1027,6 @@ Applied as jQuery method.
|
|
1004
1027
|
},
|
1005
1028
|
|
1006
1029
|
save: function(e, params) {
|
1007
|
-
this.hide('save');
|
1008
1030
|
/**
|
1009
1031
|
Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance
|
1010
1032
|
|
@@ -1025,6 +1047,9 @@ Applied as jQuery method.
|
|
1025
1047
|
});
|
1026
1048
|
**/
|
1027
1049
|
this.$element.triggerHandler('save', params);
|
1050
|
+
|
1051
|
+
//hide must be after trigger, as saving value may require methods od plugin, applied to input
|
1052
|
+
this.hide('save');
|
1028
1053
|
},
|
1029
1054
|
|
1030
1055
|
/**
|
@@ -1255,12 +1280,14 @@ Applied as jQuery method.
|
|
1255
1280
|
innerHide: function () {
|
1256
1281
|
this.$tip.hide(this.options.anim, $.proxy(function() {
|
1257
1282
|
this.$element.show();
|
1258
|
-
this.
|
1283
|
+
this.innerDestroy();
|
1259
1284
|
}, this));
|
1260
1285
|
},
|
1261
1286
|
|
1262
1287
|
innerDestroy: function() {
|
1263
|
-
this.tip()
|
1288
|
+
if(this.tip()) {
|
1289
|
+
this.tip().empty().remove();
|
1290
|
+
}
|
1264
1291
|
}
|
1265
1292
|
});
|
1266
1293
|
|
@@ -1275,8 +1302,13 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1275
1302
|
|
1276
1303
|
var Editable = function (element, options) {
|
1277
1304
|
this.$element = $(element);
|
1278
|
-
|
1279
|
-
this.
|
1305
|
+
//data-* has more priority over js options: because dynamically created elements may change data-*
|
1306
|
+
this.options = $.extend({}, $.fn.editable.defaults, options, $.fn.editableutils.getConfigData(this.$element));
|
1307
|
+
if(this.options.selector) {
|
1308
|
+
this.initLive();
|
1309
|
+
} else {
|
1310
|
+
this.init();
|
1311
|
+
}
|
1280
1312
|
};
|
1281
1313
|
|
1282
1314
|
Editable.prototype = {
|
@@ -1319,8 +1351,10 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1319
1351
|
if(this.options.toggle !== 'manual') {
|
1320
1352
|
this.$element.addClass('editable-click');
|
1321
1353
|
this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){
|
1354
|
+
//prevent following link
|
1322
1355
|
e.preventDefault();
|
1323
|
-
|
1356
|
+
|
1357
|
+
//stop propagation not required because in document click handler it checks event target
|
1324
1358
|
//e.stopPropagation();
|
1325
1359
|
|
1326
1360
|
if(this.options.toggle === 'mouseenter') {
|
@@ -1362,6 +1396,24 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1362
1396
|
}, this));
|
1363
1397
|
},
|
1364
1398
|
|
1399
|
+
/*
|
1400
|
+
Initializes parent element for live editables
|
1401
|
+
*/
|
1402
|
+
initLive: function() {
|
1403
|
+
//store selector
|
1404
|
+
var selector = this.options.selector;
|
1405
|
+
//modify options for child elements
|
1406
|
+
this.options.selector = false;
|
1407
|
+
this.options.autotext = 'never';
|
1408
|
+
//listen toggle events
|
1409
|
+
this.$element.on(this.options.toggle + '.editable', selector, $.proxy(function(e){
|
1410
|
+
var $target = $(e.target);
|
1411
|
+
if(!$target.data('editable')) {
|
1412
|
+
$target.editable(this.options).trigger(e);
|
1413
|
+
}
|
1414
|
+
}, this));
|
1415
|
+
},
|
1416
|
+
|
1365
1417
|
/*
|
1366
1418
|
Renders value into element's text.
|
1367
1419
|
Can call custom display method from options.
|
@@ -1375,8 +1427,8 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1375
1427
|
return;
|
1376
1428
|
}
|
1377
1429
|
|
1378
|
-
//if
|
1379
|
-
if(this.input.
|
1430
|
+
//if input has `value2htmlFinal` method, we pass callback in third param to be called when source is loaded
|
1431
|
+
if(this.input.value2htmlFinal) {
|
1380
1432
|
return this.input.value2html(this.value, this.$element[0], this.options.display, response);
|
1381
1433
|
//if display method defined --> use it
|
1382
1434
|
} else if(typeof this.options.display === 'function') {
|
@@ -1394,7 +1446,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1394
1446
|
enable: function() {
|
1395
1447
|
this.options.disabled = false;
|
1396
1448
|
this.$element.removeClass('editable-disabled');
|
1397
|
-
this.handleEmpty();
|
1449
|
+
this.handleEmpty(this.isEmpty);
|
1398
1450
|
if(this.options.toggle !== 'manual') {
|
1399
1451
|
if(this.$element.attr('tabindex') === '-1') {
|
1400
1452
|
this.$element.removeAttr('tabindex');
|
@@ -1410,7 +1462,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1410
1462
|
this.options.disabled = true;
|
1411
1463
|
this.hide();
|
1412
1464
|
this.$element.addClass('editable-disabled');
|
1413
|
-
this.handleEmpty();
|
1465
|
+
this.handleEmpty(this.isEmpty);
|
1414
1466
|
//do not stop focus on this element
|
1415
1467
|
this.$element.attr('tabindex', -1);
|
1416
1468
|
},
|
@@ -1471,27 +1523,33 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1471
1523
|
},
|
1472
1524
|
|
1473
1525
|
/*
|
1474
|
-
* set emptytext if element is empty
|
1526
|
+
* set emptytext if element is empty
|
1475
1527
|
*/
|
1476
|
-
handleEmpty: function () {
|
1528
|
+
handleEmpty: function (isEmpty) {
|
1477
1529
|
//do not handle empty if we do not display anything
|
1478
1530
|
if(this.options.display === false) {
|
1479
1531
|
return;
|
1480
1532
|
}
|
1481
1533
|
|
1482
|
-
|
1534
|
+
this.isEmpty = isEmpty !== undefined ? isEmpty : $.trim(this.$element.text()) === '';
|
1535
|
+
|
1483
1536
|
//emptytext shown only for enabled
|
1484
1537
|
if(!this.options.disabled) {
|
1485
|
-
if (
|
1486
|
-
this.$element.
|
1487
|
-
|
1488
|
-
|
1538
|
+
if (this.isEmpty) {
|
1539
|
+
this.$element.text(this.options.emptytext);
|
1540
|
+
if(this.options.emptyclass) {
|
1541
|
+
this.$element.addClass(this.options.emptyclass);
|
1542
|
+
}
|
1543
|
+
} else if(this.options.emptyclass) {
|
1544
|
+
this.$element.removeClass(this.options.emptyclass);
|
1489
1545
|
}
|
1490
1546
|
} else {
|
1491
1547
|
//below required if element disable property was changed
|
1492
|
-
if(this
|
1548
|
+
if(this.isEmpty) {
|
1493
1549
|
this.$element.empty();
|
1494
|
-
this
|
1550
|
+
if(this.options.emptyclass) {
|
1551
|
+
this.$element.removeClass(this.options.emptyclass);
|
1552
|
+
}
|
1495
1553
|
}
|
1496
1554
|
}
|
1497
1555
|
},
|
@@ -1513,6 +1571,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1513
1571
|
input: this.input //pass input to form (as it is already created)
|
1514
1572
|
});
|
1515
1573
|
this.$element.editableContainer(containerOptions);
|
1574
|
+
//listen `save` event
|
1516
1575
|
this.$element.on("save.internal", $.proxy(this.save, this));
|
1517
1576
|
this.container = this.$element.data('editableContainer');
|
1518
1577
|
} else if(this.container.tip().is(':visible')) {
|
@@ -1550,13 +1609,29 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1550
1609
|
* called when form was submitted
|
1551
1610
|
*/
|
1552
1611
|
save: function(e, params) {
|
1553
|
-
//
|
1554
|
-
if(
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1612
|
+
//mark element with unsaved class if needed
|
1613
|
+
if(this.options.unsavedclass) {
|
1614
|
+
/*
|
1615
|
+
Add unsaved css to element if:
|
1616
|
+
- url is not user's function
|
1617
|
+
- value was not sent to server
|
1618
|
+
- params.response === undefined, that means data was not sent
|
1619
|
+
- value changed
|
1620
|
+
*/
|
1621
|
+
var sent = false;
|
1622
|
+
sent = sent || typeof this.options.url === 'function';
|
1623
|
+
sent = sent || this.options.display === false;
|
1624
|
+
sent = sent || params.response !== undefined;
|
1625
|
+
sent = sent || (this.options.savenochange && this.input.value2str(this.value) !== this.input.value2str(params.newValue));
|
1626
|
+
|
1627
|
+
if(sent) {
|
1628
|
+
this.$element.removeClass(this.options.unsavedclass);
|
1629
|
+
} else {
|
1630
|
+
this.$element.addClass(this.options.unsavedclass);
|
1631
|
+
}
|
1558
1632
|
}
|
1559
1633
|
|
1634
|
+
//set new value
|
1560
1635
|
this.setValue(params.newValue, false, params.response);
|
1561
1636
|
|
1562
1637
|
/**
|
@@ -1648,7 +1723,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1648
1723
|
url: '/post',
|
1649
1724
|
pk: 1
|
1650
1725
|
});
|
1651
|
-
**/
|
1726
|
+
**/
|
1652
1727
|
$.fn.editable = function (option) {
|
1653
1728
|
//special API methods returning non-jquery object
|
1654
1729
|
var result = {}, args = arguments, datakey = 'editable';
|
@@ -1665,7 +1740,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1665
1740
|
username: "username is required",
|
1666
1741
|
fullname: "fullname should be minimum 3 letters length"
|
1667
1742
|
}
|
1668
|
-
**/
|
1743
|
+
**/
|
1669
1744
|
case 'validate':
|
1670
1745
|
this.each(function () {
|
1671
1746
|
var $this = $(this), data = $this.data(datakey), error;
|
@@ -1686,7 +1761,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1686
1761
|
username: "superuser",
|
1687
1762
|
fullname: "John"
|
1688
1763
|
}
|
1689
|
-
**/
|
1764
|
+
**/
|
1690
1765
|
case 'getValue':
|
1691
1766
|
this.each(function () {
|
1692
1767
|
var $this = $(this), data = $this.data(datakey);
|
@@ -1705,11 +1780,11 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1705
1780
|
@param {object} options
|
1706
1781
|
@param {object} options.url url to submit data
|
1707
1782
|
@param {object} options.data additional data to submit
|
1708
|
-
@param {object} options.ajaxOptions additional ajax options
|
1783
|
+
@param {object} options.ajaxOptions additional ajax options
|
1709
1784
|
@param {function} options.error(obj) error handler
|
1710
1785
|
@param {function} options.success(obj,config) success handler
|
1711
1786
|
@returns {Object} jQuery object
|
1712
|
-
**/
|
1787
|
+
**/
|
1713
1788
|
case 'submit': //collects value, validate and submit to server for creating new record
|
1714
1789
|
var config = arguments[1] || {},
|
1715
1790
|
$elems = this,
|
@@ -1860,7 +1935,51 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|
1860
1935
|
}
|
1861
1936
|
}
|
1862
1937
|
**/
|
1863
|
-
display: null
|
1938
|
+
display: null,
|
1939
|
+
/**
|
1940
|
+
Css class applied when editable text is empty.
|
1941
|
+
|
1942
|
+
@property emptyclass
|
1943
|
+
@type string
|
1944
|
+
@since 1.4.1
|
1945
|
+
@default editable-empty
|
1946
|
+
**/
|
1947
|
+
emptyclass: 'editable-empty',
|
1948
|
+
/**
|
1949
|
+
Css class applied when value was stored but not sent to server (`pk` is empty or `send = 'never'`).
|
1950
|
+
You may set it to `null` if you work with editables locally and submit them together.
|
1951
|
+
|
1952
|
+
@property unsavedclass
|
1953
|
+
@type string
|
1954
|
+
@since 1.4.1
|
1955
|
+
@default editable-unsaved
|
1956
|
+
**/
|
1957
|
+
unsavedclass: 'editable-unsaved',
|
1958
|
+
/**
|
1959
|
+
If a css selector is provided, editable will be delegated to the specified targets.
|
1960
|
+
Usefull for dynamically generated DOM elements.
|
1961
|
+
**Please note**, that delegated targets can't use `emptytext` and `autotext` options,
|
1962
|
+
as they are initialized after first click.
|
1963
|
+
|
1964
|
+
@property selector
|
1965
|
+
@type string
|
1966
|
+
@since 1.4.1
|
1967
|
+
@default null
|
1968
|
+
@example
|
1969
|
+
<div id="user">
|
1970
|
+
<a href="#" data-name="username" data-type="text" title="Username">awesome</a>
|
1971
|
+
<a href="#" data-name="group" data-type="select" data-source="/groups" data-value="1" title="Group">Operator</a>
|
1972
|
+
</div>
|
1973
|
+
|
1974
|
+
<script>
|
1975
|
+
$('#user').editable({
|
1976
|
+
selector: 'a',
|
1977
|
+
url: '/post',
|
1978
|
+
pk: 1
|
1979
|
+
});
|
1980
|
+
</script>
|
1981
|
+
**/
|
1982
|
+
selector: null
|
1864
1983
|
};
|
1865
1984
|
|
1866
1985
|
}(window.jQuery));
|
@@ -2053,15 +2172,7 @@ To create your own input you can inherit from this class.
|
|
2053
2172
|
@type string
|
2054
2173
|
@default input-medium
|
2055
2174
|
**/
|
2056
|
-
inputclass: 'input-medium'
|
2057
|
-
/**
|
2058
|
-
Name attribute of input
|
2059
|
-
|
2060
|
-
@property name
|
2061
|
-
@type string
|
2062
|
-
@default null
|
2063
|
-
**/
|
2064
|
-
name: null
|
2175
|
+
inputclass: 'input-medium'
|
2065
2176
|
};
|
2066
2177
|
|
2067
2178
|
$.extend($.fn.editabletypes, {abstractinput: AbstractInput});
|
@@ -2214,7 +2325,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2214
2325
|
}, this)
|
2215
2326
|
});
|
2216
2327
|
} else { //options as json/array/function
|
2217
|
-
if (
|
2328
|
+
if ($.isFunction(this.options.source)) {
|
2218
2329
|
this.sourceData = this.makeArray(this.options.source());
|
2219
2330
|
} else {
|
2220
2331
|
this.sourceData = this.makeArray(this.options.source);
|
@@ -2270,35 +2381,45 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2270
2381
|
* convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}]
|
2271
2382
|
*/
|
2272
2383
|
makeArray: function(data) {
|
2273
|
-
var count, obj, result = [],
|
2384
|
+
var count, obj, result = [], item, iterateItem;
|
2274
2385
|
if(!data || typeof data === 'string') {
|
2275
2386
|
return null;
|
2276
2387
|
}
|
2277
2388
|
|
2278
2389
|
if($.isArray(data)) { //array
|
2279
|
-
|
2390
|
+
/*
|
2391
|
+
function to iterate inside item of array if item is object.
|
2392
|
+
Caclulates count of keys in item and store in obj.
|
2393
|
+
*/
|
2394
|
+
iterateItem = function (k, v) {
|
2280
2395
|
obj = {value: k, text: v};
|
2281
2396
|
if(count++ >= 2) {
|
2282
|
-
return false;// exit each if
|
2397
|
+
return false;// exit from `each` if item has more than one key.
|
2283
2398
|
}
|
2284
2399
|
};
|
2285
2400
|
|
2286
2401
|
for(var i = 0; i < data.length; i++) {
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2402
|
+
item = data[i];
|
2403
|
+
if(typeof item === 'object') {
|
2404
|
+
count = 0; //count of keys inside item
|
2405
|
+
$.each(item, iterateItem);
|
2406
|
+
//case: [{val1: 'text1'}, {val2: 'text2} ...]
|
2407
|
+
if(count === 1) {
|
2291
2408
|
result.push(obj);
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2409
|
+
//case: [{value: 1, text: 'text1'}, {value: 2, text: 'text2'}, ...]
|
2410
|
+
} else if(count > 1) {
|
2411
|
+
//removed check of existance: item.hasOwnProperty('value') && item.hasOwnProperty('text')
|
2412
|
+
if(item.children) {
|
2413
|
+
item.children = this.makeArray(item.children);
|
2414
|
+
}
|
2415
|
+
result.push(item);
|
2296
2416
|
}
|
2297
2417
|
} else {
|
2298
|
-
|
2418
|
+
//case: ['text1', 'text2' ...]
|
2419
|
+
result.push({value: item, text: item});
|
2299
2420
|
}
|
2300
2421
|
}
|
2301
|
-
} else { //
|
2422
|
+
} else { //case: {val1: 'text1', val2: 'text2, ...}
|
2302
2423
|
$.each(data, function (k, v) {
|
2303
2424
|
result.push({value: k, text: v});
|
2304
2425
|
});
|
@@ -2321,12 +2442,16 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2321
2442
|
List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
2322
2443
|
/**
|
2323
2444
|
Source data for list.
|
2324
|
-
If **array** - it should be in format: `[{value: 1, text: "text1"}, {...
|
2445
|
+
If **array** - it should be in format: `[{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]`
|
2325
2446
|
For compability, object format is also supported: `{"1": "text1", "2": "text2" ...}` but it does not guarantee elements order.
|
2326
2447
|
|
2327
2448
|
If **string** - considered ajax url to load items. In that case results will be cached for fields with the same source and name. See also `sourceCache` option.
|
2328
2449
|
|
2329
2450
|
If **function**, it should return data in format above (since 1.4.0).
|
2451
|
+
|
2452
|
+
Since 1.4.1 key `children` supported to render OPTGROUP (for **select** input only).
|
2453
|
+
`[{text: "group1", children: [{value: 1, text: "text1"}, {value: 2, text: "text2"}]}, ...]`
|
2454
|
+
|
2330
2455
|
|
2331
2456
|
@property source
|
2332
2457
|
@type string | array | object | function
|
@@ -2350,8 +2475,8 @@ List - abstract class for inputs that have source option loaded from js array or
|
|
2350
2475
|
**/
|
2351
2476
|
sourceError: 'Error when loading list',
|
2352
2477
|
/**
|
2353
|
-
if <code>true</code> and source is **string url** - results will be cached for fields with the same source
|
2354
|
-
Usefull for editable
|
2478
|
+
if <code>true</code> and source is **string url** - results will be cached for fields with the same source.
|
2479
|
+
Usefull for editable column in grid to prevent extra requests.
|
2355
2480
|
|
2356
2481
|
@property sourceCache
|
2357
2482
|
@type boolean
|
@@ -2415,10 +2540,7 @@ $(function(){
|
|
2415
2540
|
.keyup($.proxy(this.toggleClear, this))
|
2416
2541
|
.parent().css('position', 'relative');
|
2417
2542
|
|
2418
|
-
this.$clear.click($.proxy(
|
2419
|
-
this.$clear.hide();
|
2420
|
-
this.$input.val('').focus();
|
2421
|
-
}, this));
|
2543
|
+
this.$clear.click($.proxy(this.clear, this));
|
2422
2544
|
}
|
2423
2545
|
},
|
2424
2546
|
|
@@ -2443,12 +2565,17 @@ $(function(){
|
|
2443
2565
|
return;
|
2444
2566
|
}
|
2445
2567
|
|
2446
|
-
if(this.$input.val()) {
|
2568
|
+
if(this.$input.val().length) {
|
2447
2569
|
this.$clear.show();
|
2448
2570
|
} else {
|
2449
2571
|
this.$clear.hide();
|
2450
2572
|
}
|
2451
|
-
}
|
2573
|
+
},
|
2574
|
+
|
2575
|
+
clear: function() {
|
2576
|
+
this.$clear.hide();
|
2577
|
+
this.$input.val('').focus();
|
2578
|
+
}
|
2452
2579
|
});
|
2453
2580
|
|
2454
2581
|
Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
@@ -2622,14 +2749,21 @@ $(function(){
|
|
2622
2749
|
$.extend(Select.prototype, {
|
2623
2750
|
renderList: function() {
|
2624
2751
|
this.$input.empty();
|
2625
|
-
|
2626
|
-
if(!$.isArray(this.sourceData)) {
|
2627
|
-
return;
|
2628
|
-
}
|
2629
2752
|
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2753
|
+
var fillItems = function($el, data) {
|
2754
|
+
if($.isArray(data)) {
|
2755
|
+
for(var i=0; i<data.length; i++) {
|
2756
|
+
if(data[i].children) {
|
2757
|
+
$el.append(fillItems($('<optgroup>', {label: data[i].text}), data[i].children));
|
2758
|
+
} else {
|
2759
|
+
$el.append($('<option>', {value: data[i].value}).text(data[i].text));
|
2760
|
+
}
|
2761
|
+
}
|
2762
|
+
}
|
2763
|
+
return $el;
|
2764
|
+
};
|
2765
|
+
|
2766
|
+
fillItems(this.$input, this.sourceData);
|
2633
2767
|
|
2634
2768
|
this.setClass();
|
2635
2769
|
|
@@ -2714,8 +2848,7 @@ $(function(){
|
|
2714
2848
|
for(var i=0; i<this.sourceData.length; i++) {
|
2715
2849
|
$label = $('<label>').append($('<input>', {
|
2716
2850
|
type: 'checkbox',
|
2717
|
-
value: this.sourceData[i].value
|
2718
|
-
name: this.options.name
|
2851
|
+
value: this.sourceData[i].value
|
2719
2852
|
}))
|
2720
2853
|
.append($('<span>').text(' '+this.sourceData[i].text));
|
2721
2854
|
|
@@ -2744,7 +2877,7 @@ $(function(){
|
|
2744
2877
|
|
2745
2878
|
//set checked on required checkboxes
|
2746
2879
|
value2input: function(value) {
|
2747
|
-
this.$input.
|
2880
|
+
this.$input.prop('checked', false);
|
2748
2881
|
if($.isArray(value) && value.length) {
|
2749
2882
|
this.$input.each(function(i, el) {
|
2750
2883
|
var $el = $(el);
|
@@ -2753,7 +2886,7 @@ $(function(){
|
|
2753
2886
|
/*jslint eqeq: true*/
|
2754
2887
|
if($el.val() == val) {
|
2755
2888
|
/*jslint eqeq: false*/
|
2756
|
-
$el.
|
2889
|
+
$el.prop('checked', true);
|
2757
2890
|
}
|
2758
2891
|
});
|
2759
2892
|
});
|
@@ -2992,6 +3125,199 @@ Range (inherit from number)
|
|
2992
3125
|
$.fn.editabletypes.range = Range;
|
2993
3126
|
}(window.jQuery));
|
2994
3127
|
/**
|
3128
|
+
Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
|
3129
|
+
Please see [original docs](http://ivaynberg.github.com/select2) for detailed description and options.
|
3130
|
+
You should manually include select2 distributive:
|
3131
|
+
|
3132
|
+
<link href="select2/select2.css" rel="stylesheet" type="text/css"></link>
|
3133
|
+
<script src="select2/select2.js"></script>
|
3134
|
+
|
3135
|
+
@class select2
|
3136
|
+
@extends abstractinput
|
3137
|
+
@since 1.4.1
|
3138
|
+
@final
|
3139
|
+
@example
|
3140
|
+
<a href="#" id="country" data-type="select2" data-pk="1" data-value="ru" data-url="/post" data-original-title="Select country"></a>
|
3141
|
+
<script>
|
3142
|
+
$(function(){
|
3143
|
+
$('#country').editable({
|
3144
|
+
source: [
|
3145
|
+
{id: 'gb', text: 'Great Britain'},
|
3146
|
+
{id: 'us', text: 'United States'},
|
3147
|
+
{id: 'ru', text: 'Russia'}
|
3148
|
+
],
|
3149
|
+
select2: {
|
3150
|
+
multiple: true
|
3151
|
+
}
|
3152
|
+
});
|
3153
|
+
});
|
3154
|
+
</script>
|
3155
|
+
**/
|
3156
|
+
(function ($) {
|
3157
|
+
|
3158
|
+
var Constructor = function (options) {
|
3159
|
+
this.init('select2', options, Constructor.defaults);
|
3160
|
+
|
3161
|
+
options.select2 = options.select2 || {};
|
3162
|
+
|
3163
|
+
var that = this,
|
3164
|
+
mixin = {
|
3165
|
+
placeholder: options.placeholder
|
3166
|
+
};
|
3167
|
+
|
3168
|
+
//detect whether it is multi-valued
|
3169
|
+
this.isMultiple = options.select2.tags || options.select2.multiple;
|
3170
|
+
|
3171
|
+
//if not `tags` mode, we need define init set data from source
|
3172
|
+
if(!options.select2.tags) {
|
3173
|
+
if(options.source) {
|
3174
|
+
mixin.data = options.source;
|
3175
|
+
}
|
3176
|
+
|
3177
|
+
//this function can be defaulted in seletc2. See https://github.com/ivaynberg/select2/issues/710
|
3178
|
+
mixin.initSelection = function (element, callback) {
|
3179
|
+
var val = that.str2value(element.val()),
|
3180
|
+
data = $.fn.editableutils.itemsByValue(val, mixin.data, 'id');
|
3181
|
+
|
3182
|
+
//for single-valued mode should not use array. Take first element instead.
|
3183
|
+
if($.isArray(data) && data.length && !that.isMultiple) {
|
3184
|
+
data = data[0];
|
3185
|
+
}
|
3186
|
+
|
3187
|
+
callback(data);
|
3188
|
+
};
|
3189
|
+
}
|
3190
|
+
|
3191
|
+
//overriding objects in config (as by default jQuery extend() is not recursive)
|
3192
|
+
this.options.select2 = $.extend({}, Constructor.defaults.select2, mixin, options.select2);
|
3193
|
+
};
|
3194
|
+
|
3195
|
+
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
|
3196
|
+
|
3197
|
+
$.extend(Constructor.prototype, {
|
3198
|
+
render: function() {
|
3199
|
+
this.setClass();
|
3200
|
+
//apply select2
|
3201
|
+
this.$input.select2(this.options.select2);
|
3202
|
+
|
3203
|
+
//trigger resize of editableform to re-position container in multi-valued mode
|
3204
|
+
if(this.isMultiple) {
|
3205
|
+
this.$input.on('change', function() {
|
3206
|
+
$(this).closest('form').parent().triggerHandler('resize');
|
3207
|
+
});
|
3208
|
+
}
|
3209
|
+
|
3210
|
+
},
|
3211
|
+
|
3212
|
+
value2html: function(value, element) {
|
3213
|
+
var text = '', data;
|
3214
|
+
if(this.$input) { //when submitting form
|
3215
|
+
data = this.$input.select2('data');
|
3216
|
+
} else { //on init (autotext)
|
3217
|
+
//here select2 instance not created yet and data may be even not loaded.
|
3218
|
+
//we can check data/tags property of select config and if exist lookup text
|
3219
|
+
if(this.options.select2.tags) {
|
3220
|
+
data = value;
|
3221
|
+
} else if(this.options.select2.data) {
|
3222
|
+
data = $.fn.editableutils.itemsByValue(value, this.options.select2.data, 'id');
|
3223
|
+
}
|
3224
|
+
}
|
3225
|
+
|
3226
|
+
if($.isArray(data)) {
|
3227
|
+
//collect selected data and show with separator
|
3228
|
+
text = [];
|
3229
|
+
$.each(data, function(k, v){
|
3230
|
+
text.push(v && typeof v === 'object' ? v.text : v);
|
3231
|
+
});
|
3232
|
+
} else if(data) {
|
3233
|
+
text = data.text;
|
3234
|
+
}
|
3235
|
+
|
3236
|
+
text = $.isArray(text) ? text.join(this.options.viewseparator) : text;
|
3237
|
+
|
3238
|
+
$(element).text(text);
|
3239
|
+
},
|
3240
|
+
|
3241
|
+
html2value: function(html) {
|
3242
|
+
return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null;
|
3243
|
+
},
|
3244
|
+
|
3245
|
+
value2input: function(value) {
|
3246
|
+
this.$input.val(value).trigger('change');
|
3247
|
+
},
|
3248
|
+
|
3249
|
+
input2value: function() {
|
3250
|
+
return this.$input.select2('val');
|
3251
|
+
},
|
3252
|
+
|
3253
|
+
str2value: function(str, separator) {
|
3254
|
+
if(typeof str !== 'string' || !this.isMultiple) {
|
3255
|
+
return str;
|
3256
|
+
}
|
3257
|
+
|
3258
|
+
separator = separator || this.options.select2.separator || $.fn.select2.defaults.separator;
|
3259
|
+
|
3260
|
+
var val, i, l;
|
3261
|
+
|
3262
|
+
if (str === null || str.length < 1) {
|
3263
|
+
return null;
|
3264
|
+
}
|
3265
|
+
val = str.split(separator);
|
3266
|
+
for (i = 0, l = val.length; i < l; i = i + 1) {
|
3267
|
+
val[i] = $.trim(val[i]);
|
3268
|
+
}
|
3269
|
+
|
3270
|
+
return val;
|
3271
|
+
}
|
3272
|
+
|
3273
|
+
});
|
3274
|
+
|
3275
|
+
Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
3276
|
+
/**
|
3277
|
+
@property tpl
|
3278
|
+
@default <input type="hidden">
|
3279
|
+
**/
|
3280
|
+
tpl:'<input type="hidden">',
|
3281
|
+
/**
|
3282
|
+
Configuration of select2. [Full list of options](http://ivaynberg.github.com/select2).
|
3283
|
+
|
3284
|
+
@property select2
|
3285
|
+
@type object
|
3286
|
+
@default null
|
3287
|
+
**/
|
3288
|
+
select2: null,
|
3289
|
+
/**
|
3290
|
+
Placeholder attribute of select
|
3291
|
+
|
3292
|
+
@property placeholder
|
3293
|
+
@type string
|
3294
|
+
@default null
|
3295
|
+
**/
|
3296
|
+
placeholder: null,
|
3297
|
+
/**
|
3298
|
+
Source data for select. It will be assigned to select2 `data` property and kept here just for convenience.
|
3299
|
+
Please note, that format is different from simple `select` input: use 'id' instead of 'value'.
|
3300
|
+
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
|
3301
|
+
|
3302
|
+
@property source
|
3303
|
+
@type array
|
3304
|
+
@default null
|
3305
|
+
**/
|
3306
|
+
source: null,
|
3307
|
+
/**
|
3308
|
+
Separator used to display tags.
|
3309
|
+
|
3310
|
+
@property viewseparator
|
3311
|
+
@type string
|
3312
|
+
@default ', '
|
3313
|
+
**/
|
3314
|
+
viewseparator: ', '
|
3315
|
+
});
|
3316
|
+
|
3317
|
+
$.fn.editabletypes.select2 = Constructor;
|
3318
|
+
|
3319
|
+
}(window.jQuery));
|
3320
|
+
/**
|
2995
3321
|
* Combodate - 1.0.1
|
2996
3322
|
* Dropdown date and time picker.
|
2997
3323
|
* Converts text input into dropdowns to pick day, month, year, hour, minute and second.
|
@@ -4934,3 +5260,225 @@ Automatically shown in inline mode.
|
|
4934
5260
|
$.fn.datepicker.DPGlobal = DPGlobal;
|
4935
5261
|
|
4936
5262
|
}( window.jQuery );
|
5263
|
+
|
5264
|
+
/**
|
5265
|
+
Typeahead input (bootstrap only). Based on Twitter Bootstrap [typeahead](http://twitter.github.com/bootstrap/javascript.html#typeahead).
|
5266
|
+
Depending on `source` format typeahead operates in two modes:
|
5267
|
+
|
5268
|
+
* **strings**:
|
5269
|
+
When `source` defined as array of strings, e.g. `['text1', 'text2', 'text3' ...]`.
|
5270
|
+
User can submit one of these strings or any text entered in input (even if it is not matching source).
|
5271
|
+
|
5272
|
+
* **objects**:
|
5273
|
+
When `source` defined as array of objects, e.g. `[{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]`.
|
5274
|
+
User can submit only values that are in source (otherwise `null` is submitted). This is more like *dropdown* behavior.
|
5275
|
+
|
5276
|
+
@class typeahead
|
5277
|
+
@extends list
|
5278
|
+
@since 1.4.1
|
5279
|
+
@final
|
5280
|
+
@example
|
5281
|
+
<a href="#" id="country" data-type="typeahead" data-pk="1" data-url="/post" data-original-title="Input country"></a>
|
5282
|
+
<script>
|
5283
|
+
$(function(){
|
5284
|
+
$('#country').editable({
|
5285
|
+
value: 'ru',
|
5286
|
+
source: [
|
5287
|
+
{value: 'gb', text: 'Great Britain'},
|
5288
|
+
{value: 'us', text: 'United States'},
|
5289
|
+
{value: 'ru', text: 'Russia'}
|
5290
|
+
]
|
5291
|
+
}
|
5292
|
+
});
|
5293
|
+
});
|
5294
|
+
</script>
|
5295
|
+
**/
|
5296
|
+
(function ($) {
|
5297
|
+
|
5298
|
+
var Constructor = function (options) {
|
5299
|
+
this.init('typeahead', options, Constructor.defaults);
|
5300
|
+
|
5301
|
+
//overriding objects in config (as by default jQuery extend() is not recursive)
|
5302
|
+
this.options.typeahead = $.extend({}, Constructor.defaults.typeahead, {
|
5303
|
+
//set default methods for typeahead to work with objects
|
5304
|
+
matcher: this.matcher,
|
5305
|
+
sorter: this.sorter,
|
5306
|
+
highlighter: this.highlighter,
|
5307
|
+
updater: this.updater
|
5308
|
+
}, options.typeahead);
|
5309
|
+
};
|
5310
|
+
|
5311
|
+
$.fn.editableutils.inherit(Constructor, $.fn.editabletypes.list);
|
5312
|
+
|
5313
|
+
$.extend(Constructor.prototype, {
|
5314
|
+
renderList: function() {
|
5315
|
+
this.$input = this.$tpl.is('input') ? this.$tpl : this.$tpl.find('input[type="text"]');
|
5316
|
+
|
5317
|
+
//set source of typeahead
|
5318
|
+
this.options.typeahead.source = this.sourceData;
|
5319
|
+
|
5320
|
+
//apply typeahead
|
5321
|
+
this.$input.typeahead(this.options.typeahead);
|
5322
|
+
|
5323
|
+
//attach own render method
|
5324
|
+
this.$input.data('typeahead').render = $.proxy(this.typeaheadRender, this.$input.data('typeahead'));
|
5325
|
+
|
5326
|
+
this.renderClear();
|
5327
|
+
this.setClass();
|
5328
|
+
this.setAttr('placeholder');
|
5329
|
+
},
|
5330
|
+
|
5331
|
+
value2htmlFinal: function(value, element) {
|
5332
|
+
if(this.getIsObjects()) {
|
5333
|
+
var items = $.fn.editableutils.itemsByValue(value, this.sourceData);
|
5334
|
+
$(element).text(items.length ? items[0].text : '');
|
5335
|
+
} else {
|
5336
|
+
$(element).text(value);
|
5337
|
+
}
|
5338
|
+
},
|
5339
|
+
|
5340
|
+
html2value: function (html) {
|
5341
|
+
return html ? html : null;
|
5342
|
+
},
|
5343
|
+
|
5344
|
+
value2input: function(value) {
|
5345
|
+
if(this.getIsObjects()) {
|
5346
|
+
var items = $.fn.editableutils.itemsByValue(value, this.sourceData);
|
5347
|
+
this.$input.data('value', value).val(items.length ? items[0].text : '');
|
5348
|
+
} else {
|
5349
|
+
this.$input.val(value);
|
5350
|
+
}
|
5351
|
+
},
|
5352
|
+
|
5353
|
+
input2value: function() {
|
5354
|
+
if(this.getIsObjects()) {
|
5355
|
+
var value = this.$input.data('value'),
|
5356
|
+
items = $.fn.editableutils.itemsByValue(value, this.sourceData);
|
5357
|
+
|
5358
|
+
if(items.length && items[0].text.toLowerCase() === this.$input.val().toLowerCase()) {
|
5359
|
+
return value;
|
5360
|
+
} else {
|
5361
|
+
return null; //entered string not found in source
|
5362
|
+
}
|
5363
|
+
} else {
|
5364
|
+
return this.$input.val();
|
5365
|
+
}
|
5366
|
+
},
|
5367
|
+
|
5368
|
+
/*
|
5369
|
+
if in sourceData values <> texts, typeahead in "objects" mode:
|
5370
|
+
user must pick some value from list, otherwise `null` returned.
|
5371
|
+
if all values == texts put typeahead in "strings" mode:
|
5372
|
+
anything what entered is submited.
|
5373
|
+
*/
|
5374
|
+
getIsObjects: function() {
|
5375
|
+
if(this.isObjects === undefined) {
|
5376
|
+
this.isObjects = false;
|
5377
|
+
for(var i=0; i<this.sourceData.length; i++) {
|
5378
|
+
if(this.sourceData[i].value !== this.sourceData[i].text) {
|
5379
|
+
this.isObjects = true;
|
5380
|
+
break;
|
5381
|
+
}
|
5382
|
+
}
|
5383
|
+
}
|
5384
|
+
return this.isObjects;
|
5385
|
+
},
|
5386
|
+
|
5387
|
+
/*
|
5388
|
+
Methods borrowed from text input
|
5389
|
+
*/
|
5390
|
+
activate: $.fn.editabletypes.text.prototype.activate,
|
5391
|
+
renderClear: $.fn.editabletypes.text.prototype.renderClear,
|
5392
|
+
postrender: $.fn.editabletypes.text.prototype.postrender,
|
5393
|
+
toggleClear: $.fn.editabletypes.text.prototype.toggleClear,
|
5394
|
+
clear: function() {
|
5395
|
+
$.fn.editabletypes.text.prototype.clear.call(this);
|
5396
|
+
this.$input.data('value', '');
|
5397
|
+
},
|
5398
|
+
|
5399
|
+
|
5400
|
+
/*
|
5401
|
+
Typeahead option methods used as defaults
|
5402
|
+
*/
|
5403
|
+
/*jshint eqeqeq:false, curly: false, laxcomma: true*/
|
5404
|
+
matcher: function (item) {
|
5405
|
+
return $.fn.typeahead.Constructor.prototype.matcher.call(this, item.text);
|
5406
|
+
},
|
5407
|
+
sorter: function (items) {
|
5408
|
+
var beginswith = []
|
5409
|
+
, caseSensitive = []
|
5410
|
+
, caseInsensitive = []
|
5411
|
+
, item
|
5412
|
+
, text;
|
5413
|
+
|
5414
|
+
while (item = items.shift()) {
|
5415
|
+
text = item.text;
|
5416
|
+
if (!text.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item);
|
5417
|
+
else if (~text.indexOf(this.query)) caseSensitive.push(item);
|
5418
|
+
else caseInsensitive.push(item);
|
5419
|
+
}
|
5420
|
+
|
5421
|
+
return beginswith.concat(caseSensitive, caseInsensitive);
|
5422
|
+
},
|
5423
|
+
highlighter: function (item) {
|
5424
|
+
return $.fn.typeahead.Constructor.prototype.highlighter.call(this, item.text);
|
5425
|
+
},
|
5426
|
+
updater: function (item) {
|
5427
|
+
item = this.$menu.find('.active').data('item');
|
5428
|
+
this.$element.data('value', item.value);
|
5429
|
+
return item.text;
|
5430
|
+
},
|
5431
|
+
|
5432
|
+
|
5433
|
+
/*
|
5434
|
+
Overwrite typeahead's render method to store objects.
|
5435
|
+
There are a lot of disscussion in bootstrap repo on this point and still no result.
|
5436
|
+
See https://github.com/twitter/bootstrap/issues/5967
|
5437
|
+
|
5438
|
+
This function just store item in via jQuery data() method instead of attr('data-value')
|
5439
|
+
*/
|
5440
|
+
typeaheadRender: function (items) {
|
5441
|
+
var that = this;
|
5442
|
+
|
5443
|
+
items = $(items).map(function (i, item) {
|
5444
|
+
// i = $(that.options.item).attr('data-value', item)
|
5445
|
+
i = $(that.options.item).data('item', item);
|
5446
|
+
i.find('a').html(that.highlighter(item));
|
5447
|
+
return i[0];
|
5448
|
+
});
|
5449
|
+
|
5450
|
+
items.first().addClass('active');
|
5451
|
+
this.$menu.html(items);
|
5452
|
+
return this;
|
5453
|
+
}
|
5454
|
+
/*jshint eqeqeq: true, curly: true, laxcomma: false*/
|
5455
|
+
|
5456
|
+
});
|
5457
|
+
|
5458
|
+
Constructor.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
|
5459
|
+
/**
|
5460
|
+
@property tpl
|
5461
|
+
@default <input type="text">
|
5462
|
+
**/
|
5463
|
+
tpl:'<input type="text">',
|
5464
|
+
/**
|
5465
|
+
Configuration of typeahead. [Full list of options](http://twitter.github.com/bootstrap/javascript.html#typeahead).
|
5466
|
+
|
5467
|
+
@property typeahead
|
5468
|
+
@type object
|
5469
|
+
@default null
|
5470
|
+
**/
|
5471
|
+
typeahead: null,
|
5472
|
+
/**
|
5473
|
+
Whether to show `clear` button
|
5474
|
+
|
5475
|
+
@property clear
|
5476
|
+
@type boolean
|
5477
|
+
@default true
|
5478
|
+
**/
|
5479
|
+
clear: true
|
5480
|
+
});
|
5481
|
+
|
5482
|
+
$.fn.editabletypes.typeahead = Constructor;
|
5483
|
+
|
5484
|
+
}(window.jQuery));
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! X-editable - v1.4.
|
1
|
+
/*! X-editable - v1.4.1
|
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 */
|
@@ -116,21 +116,6 @@
|
|
116
116
|
.editable-clear-x:hover {
|
117
117
|
opacity: 1;
|
118
118
|
}
|
119
|
-
|
120
|
-
/*
|
121
|
-
.editable-clear-x1 {
|
122
|
-
background: image-url('clear.png') center center no-repeat;
|
123
|
-
display: inline-block;
|
124
|
-
zoom: 1;
|
125
|
-
*display: inline;
|
126
|
-
width: 13px;
|
127
|
-
height: 13px;
|
128
|
-
vertical-align: middle;
|
129
|
-
position: relative;
|
130
|
-
margin-left: -20px;
|
131
|
-
}
|
132
|
-
*/
|
133
|
-
|
134
119
|
.editable-container {
|
135
120
|
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
136
121
|
}
|
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.
|
4
|
+
version: 1.4.1
|
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-01-
|
12
|
+
date: 2013-01-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- .gitignore
|
70
70
|
- Gemfile
|
71
71
|
- README.md
|
72
|
+
- Rakefile
|
72
73
|
- X-EDITABLE-LICENSE-MIT
|
73
74
|
- bootstrap-x-editable-rails.gemspec
|
74
75
|
- bootstrap-x-editable-rails.sublime-project
|
@@ -76,6 +77,7 @@ files:
|
|
76
77
|
- lib/bootstrap-x-editable-rails/engine.rb
|
77
78
|
- lib/bootstrap-x-editable-rails/railtie.rb
|
78
79
|
- lib/bootstrap-x-editable-rails/version.rb
|
80
|
+
- vendor/assets/images/clear.png
|
79
81
|
- vendor/assets/images/loading.gif
|
80
82
|
- vendor/assets/javascripts/bootstrap-editable-inline.js
|
81
83
|
- vendor/assets/javascripts/bootstrap-editable.js
|
@@ -94,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
96
|
version: '0'
|
95
97
|
segments:
|
96
98
|
- 0
|
97
|
-
hash:
|
99
|
+
hash: 1222445192061243716
|
98
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
101
|
none: false
|
100
102
|
requirements:
|
@@ -103,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
105
|
version: '0'
|
104
106
|
segments:
|
105
107
|
- 0
|
106
|
-
hash:
|
108
|
+
hash: 1222445192061243716
|
107
109
|
requirements: []
|
108
110
|
rubyforge_project:
|
109
111
|
rubygems_version: 1.8.24
|