in_place_edit_with_datepicker 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/in_place_edit_with_datepicker.gemspec +24 -0
- data/lib/assets/javascripts/best_in_place.jquery-ui.js +58 -0
- data/lib/assets/javascripts/best_in_place.js +663 -0
- data/lib/assets/javascripts/best_in_place.purr.js +20 -0
- data/lib/assets/javascripts/best_in_place_datetime.js +52 -0
- data/lib/assets/javascripts/best_in_place_datetime.js.coffee +56 -0
- data/lib/best_in_place.rb +33 -0
- data/lib/best_in_place/controller_extensions.rb +25 -0
- data/lib/best_in_place/display_methods.rb +49 -0
- data/lib/best_in_place/engine.rb +8 -0
- data/lib/best_in_place/helper.rb +204 -0
- data/lib/best_in_place/railtie.rb +10 -0
- data/lib/best_in_place/test_helpers.rb +61 -0
- data/lib/best_in_place/utils.rb +29 -0
- data/lib/best_in_place/version.rb +3 -0
- data/lib/in_place_edit_with_datepicker.rb +7 -0
- data/lib/in_place_edit_with_datepicker/version.rb +3 -0
- data/vendor/assets/javascripts/jquery.autosize.js +272 -0
- data/vendor/assets/javascripts/jquery.purr.js +135 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 71091b6f9913d5cef546bfbc8fc9a052b2593d08
|
4
|
+
data.tar.gz: c33ba645faa7b55b314a7bcd63a70bcdd8039988
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6a45e8ce37580aa70aa5ba05a39636eb753159731c8a025bfa8c3b9820734519fed9a4943c74656554e6956d0bb4344fa81a79b356aa282d4babbb6faa7815e
|
7
|
+
data.tar.gz: 0116203acfdbb1255a068888063963866e8984acc1b3659072c68e3dc52f2965967103691a2905d0492a713bf09f11f8e0575df21f762888dd47f788e2ed8802
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Aastha Kesarwani-TCS
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# InPlaceEditWithDatepicker
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'in_place_edit_with_datepicker'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install in_place_edit_with_datepicker
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/[my-github-username]/in_place_edit_with_datepicker/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'in_place_edit_with_datepicker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "in_place_edit_with_datepicker"
|
8
|
+
spec.version = InPlaceEditWithDatepicker::VERSION
|
9
|
+
spec.authors = ["Aastha Kesarwani","Ekta Verma"]
|
10
|
+
spec.email = ["aastha.baloda@gmail.com","eku4evr@gmail.com"]
|
11
|
+
spec.summary = %q{"This gem extends best_in_place gem to include a datepicker"}
|
12
|
+
spec.description = %q{"It uses javascript to invoke jquery ui datepicker and timepicker to inline edit datetime fields"}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "best_in_place", "~> 3.0.1"
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
/*
|
2
|
+
* BestInPlace 3.0.0.alpha (2014)
|
3
|
+
*
|
4
|
+
* Depends:
|
5
|
+
* best_in_place.js
|
6
|
+
* jquery.ui.datepicker.js
|
7
|
+
*/
|
8
|
+
/*global BestInPlaceEditor */
|
9
|
+
BestInPlaceEditor.forms.date = {
|
10
|
+
activateForm: function () {
|
11
|
+
'use strict';
|
12
|
+
var that = this,
|
13
|
+
output = jQuery(document.createElement('form'))
|
14
|
+
.addClass('form_in_place')
|
15
|
+
.attr('action', 'javascript:void(0);')
|
16
|
+
.attr('style', 'display:inline'),
|
17
|
+
input_elt = jQuery(document.createElement('input'))
|
18
|
+
.attr('type', 'text')
|
19
|
+
.attr('name', this.attributeName)
|
20
|
+
.attr('value', this.sanitizeValue(this.display_value));
|
21
|
+
|
22
|
+
if (this.inner_class !== null) {
|
23
|
+
input_elt.addClass(this.inner_class);
|
24
|
+
}
|
25
|
+
output.append(input_elt);
|
26
|
+
|
27
|
+
this.element.html(output);
|
28
|
+
this.setHtmlAttributes();
|
29
|
+
this.element.find('input')[0].select();
|
30
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
31
|
+
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
32
|
+
|
33
|
+
this.element.find('input')
|
34
|
+
.datepicker({
|
35
|
+
onClose: function () {
|
36
|
+
that.update();
|
37
|
+
}
|
38
|
+
})
|
39
|
+
.datepicker('show');
|
40
|
+
},
|
41
|
+
|
42
|
+
getValue: function () {
|
43
|
+
'use strict';
|
44
|
+
return this.sanitizeValue(this.element.find("input").val());
|
45
|
+
},
|
46
|
+
|
47
|
+
submitHandler: function (event) {
|
48
|
+
'use strict';
|
49
|
+
event.data.editor.update();
|
50
|
+
},
|
51
|
+
|
52
|
+
keyupHandler: function (event) {
|
53
|
+
'use strict';
|
54
|
+
if (event.keyCode === 27) {
|
55
|
+
event.data.editor.abort();
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
@@ -0,0 +1,663 @@
|
|
1
|
+
/*
|
2
|
+
* BestInPlace (for jQuery)
|
3
|
+
* version: 3.0.0.alpha (2014)
|
4
|
+
*
|
5
|
+
* By Bernat Farrero based on the work of Jan Varwig.
|
6
|
+
* Examples at http://bernatfarrero.com
|
7
|
+
*
|
8
|
+
* Licensed under the MIT:
|
9
|
+
* http://www.opensource.org/licenses/mit-license.php
|
10
|
+
*
|
11
|
+
* @requires jQuery
|
12
|
+
*
|
13
|
+
* Usage:
|
14
|
+
*
|
15
|
+
* Attention.
|
16
|
+
* The format of the JSON object given to the select inputs is the following:
|
17
|
+
* [["key", "value"],["key", "value"]]
|
18
|
+
* The format of the JSON object given to the checkbox inputs is the following:
|
19
|
+
* ["falseValue", "trueValue"]
|
20
|
+
|
21
|
+
*/
|
22
|
+
//= require jquery.autosize
|
23
|
+
|
24
|
+
function BestInPlaceEditor(e) {
|
25
|
+
'use strict';
|
26
|
+
this.element = e;
|
27
|
+
this.initOptions();
|
28
|
+
this.bindForm();
|
29
|
+
this.initPlaceHolder();
|
30
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
31
|
+
}
|
32
|
+
|
33
|
+
BestInPlaceEditor.prototype = {
|
34
|
+
// Public Interface Functions //////////////////////////////////////////////
|
35
|
+
|
36
|
+
activate: function () {
|
37
|
+
'use strict';
|
38
|
+
var to_display;
|
39
|
+
if (this.isPlaceHolder()) {
|
40
|
+
to_display = "";
|
41
|
+
} else if (this.original_content) {
|
42
|
+
to_display = this.original_content;
|
43
|
+
} else {
|
44
|
+
switch (this.formType) {
|
45
|
+
case 'input':
|
46
|
+
case 'textarea':
|
47
|
+
if (this.display_raw) {
|
48
|
+
to_display = this.element.html().replace(/&/gi, '&');
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
var value = this.element.data('bipValue');
|
52
|
+
if (typeof value === 'undefined') {
|
53
|
+
to_display = '';
|
54
|
+
} else if (typeof value === 'string') {
|
55
|
+
to_display = this.element.data('bipValue').replace(/&/gi, '&');
|
56
|
+
} else {
|
57
|
+
to_display = this.element.data('bipValue');
|
58
|
+
}
|
59
|
+
}
|
60
|
+
break;
|
61
|
+
case 'select':
|
62
|
+
to_display = this.element.html();
|
63
|
+
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
this.oldValue = this.isPlaceHolder() ? "" : this.element.html();
|
68
|
+
this.display_value = to_display;
|
69
|
+
jQuery(this.activator).unbind("click", this.clickHandler);
|
70
|
+
this.activateForm();
|
71
|
+
this.element.trigger(jQuery.Event("best_in_place:activate"));
|
72
|
+
},
|
73
|
+
|
74
|
+
abort: function () {
|
75
|
+
'use strict';
|
76
|
+
this.activateText(this.oldValue);
|
77
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
78
|
+
this.element.trigger(jQuery.Event("best_in_place:abort"));
|
79
|
+
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
80
|
+
},
|
81
|
+
|
82
|
+
abortIfConfirm: function () {
|
83
|
+
'use strict';
|
84
|
+
if (!this.useConfirm) {
|
85
|
+
this.abort();
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
if (confirm(BestInPlaceEditor.defaults.locales[''].confirmMessage)) {
|
90
|
+
this.abort();
|
91
|
+
}
|
92
|
+
},
|
93
|
+
|
94
|
+
update: function () {
|
95
|
+
'use strict';
|
96
|
+
var editor = this,
|
97
|
+
value = this.getValue();
|
98
|
+
|
99
|
+
// Avoid request if no change is made
|
100
|
+
if (this.formType in {"input": 1, "textarea": 1} && value === this.oldValue) {
|
101
|
+
this.abort();
|
102
|
+
return true;
|
103
|
+
}
|
104
|
+
|
105
|
+
editor.ajax({
|
106
|
+
"type": BestInPlaceEditor.defaults.ajaxMethod,
|
107
|
+
"dataType": BestInPlaceEditor.defaults.ajaxDataType,
|
108
|
+
"data": editor.requestData(),
|
109
|
+
"success": function (data, status, xhr) {
|
110
|
+
editor.loadSuccessCallback(data, status, xhr);
|
111
|
+
},
|
112
|
+
"error": function (request, error) {
|
113
|
+
editor.loadErrorCallback(request, error);
|
114
|
+
}
|
115
|
+
});
|
116
|
+
|
117
|
+
|
118
|
+
switch (this.formType) {
|
119
|
+
case "select":
|
120
|
+
this.previousCollectionValue = value;
|
121
|
+
|
122
|
+
// search for the text for the span
|
123
|
+
$.each(this.values, function(index, arr){ if (String(arr[0]) === String(value)) editor.element.html(arr[1]); });
|
124
|
+
break;
|
125
|
+
|
126
|
+
case "checkbox":
|
127
|
+
$.each(this.values, function(index, arr){ if (String(arr[0]) === String(value)) editor.element.html(arr[1]); });
|
128
|
+
break;
|
129
|
+
|
130
|
+
default:
|
131
|
+
if (value !== "") {
|
132
|
+
if (this.display_raw) {
|
133
|
+
editor.element.html(value);
|
134
|
+
} else {
|
135
|
+
editor.element.text(value);
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
editor.element.html(this.placeHolder);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
editor.element.data('bipValue', value);
|
143
|
+
editor.element.attr('data-bip-value', value);
|
144
|
+
|
145
|
+
editor.element.trigger(jQuery.Event("best_in_place:update"));
|
146
|
+
|
147
|
+
|
148
|
+
},
|
149
|
+
|
150
|
+
activateForm: function () {
|
151
|
+
'use strict';
|
152
|
+
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
153
|
+
},
|
154
|
+
|
155
|
+
activateText: function (value) {
|
156
|
+
'use strict';
|
157
|
+
this.element.html(value);
|
158
|
+
if (this.isPlaceHolder()) {
|
159
|
+
this.element.html(this.placeHolder);
|
160
|
+
}
|
161
|
+
},
|
162
|
+
|
163
|
+
// Helper Functions ////////////////////////////////////////////////////////
|
164
|
+
|
165
|
+
initOptions: function () {
|
166
|
+
// Try parent supplied info
|
167
|
+
'use strict';
|
168
|
+
var self = this;
|
169
|
+
self.element.parents().each(function () {
|
170
|
+
var $parent = jQuery(this);
|
171
|
+
self.url = self.url || $parent.data("bipUrl");
|
172
|
+
self.activator = self.activator || $parent.data("bipActivator");
|
173
|
+
self.okButton = self.okButton || $parent.data("bipOkButton");
|
174
|
+
self.okButtonClass = self.okButtonClass || $parent.data("bipOkButtonClass");
|
175
|
+
self.cancelButton = self.cancelButton || $parent.data("bipCancelButton");
|
176
|
+
self.cancelButtonClass = self.cancelButtonClass || $parent.data("bipCancelButtonClass");
|
177
|
+
self.skipBlur = self.skipBlur || $parent.data("bipSkipBlur");
|
178
|
+
});
|
179
|
+
|
180
|
+
// Load own attributes (overrides all others)
|
181
|
+
self.url = self.element.data("bipUrl") || self.url || document.location.pathname;
|
182
|
+
self.collection = self.element.data("bipCollection") || self.collection;
|
183
|
+
self.formType = self.element.data("bipType") || "input";
|
184
|
+
self.objectName = self.element.data("bipObject") || self.objectName;
|
185
|
+
self.attributeName = self.element.data("bipAttribute") || self.attributeName;
|
186
|
+
self.activator = self.element.data("bipActivator") || self.element;
|
187
|
+
self.okButton = self.element.data("bipOkButton") || self.okButton;
|
188
|
+
self.okButtonClass = self.element.data("bipOkButtonClass") || self.okButtonClass || BestInPlaceEditor.defaults.okButtonClass;
|
189
|
+
self.cancelButton = self.element.data("bipCancelButton") || self.cancelButton;
|
190
|
+
self.cancelButtonClass = self.element.data("bipCancelButtonClass") || self.cancelButtonClass || BestInPlaceEditor.defaults.cancelButtonClass;
|
191
|
+
self.skipBlur = self.element.data("bipSkipBlur") || self.skipBlur || BestInPlaceEditor.defaults.skipBlur;
|
192
|
+
|
193
|
+
// Fix for default values of 0
|
194
|
+
if (self.element.data("bipPlaceholder") == null) {
|
195
|
+
self.placeHolder = BestInPlaceEditor.defaults.locales[''].placeHolder;
|
196
|
+
} else {
|
197
|
+
self.placeHolder = self.element.data("bipPlaceholder");
|
198
|
+
}
|
199
|
+
|
200
|
+
self.inner_class = self.element.data("bipInnerClass");
|
201
|
+
self.html_attrs = self.element.data("bipHtmlAttrs");
|
202
|
+
self.original_content = self.element.data("bipOriginalContent") || self.original_content;
|
203
|
+
|
204
|
+
// if set the input won't be satinized
|
205
|
+
self.display_raw = self.element.data("bip-raw");
|
206
|
+
|
207
|
+
self.useConfirm = self.element.data("bip-confirm");
|
208
|
+
|
209
|
+
if (self.formType === "select" || self.formType === "checkbox") {
|
210
|
+
self.values = self.collection;
|
211
|
+
self.collectionValue = self.element.data("bipValue") || self.collectionValue;
|
212
|
+
}
|
213
|
+
},
|
214
|
+
|
215
|
+
bindForm: function () {
|
216
|
+
'use strict';
|
217
|
+
this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
|
218
|
+
this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
|
219
|
+
},
|
220
|
+
|
221
|
+
|
222
|
+
initPlaceHolder: function () {
|
223
|
+
'use strict';
|
224
|
+
// TODO add placeholder for select and checkbox
|
225
|
+
if (this.element.html() === "") {
|
226
|
+
this.element.html(this.placeHolder);
|
227
|
+
}
|
228
|
+
},
|
229
|
+
|
230
|
+
isPlaceHolder: function () {
|
231
|
+
'use strict';
|
232
|
+
// TODO: It only work when form is deactivated.
|
233
|
+
// Condition will fail when form is activated
|
234
|
+
return this.element.html() === "" || this.element.html() === this.placeHolder;
|
235
|
+
},
|
236
|
+
|
237
|
+
getValue: function () {
|
238
|
+
'use strict';
|
239
|
+
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
240
|
+
},
|
241
|
+
|
242
|
+
// Trim and Strips HTML from text
|
243
|
+
sanitizeValue: function (s) {
|
244
|
+
'use strict';
|
245
|
+
return jQuery.trim(s);
|
246
|
+
},
|
247
|
+
|
248
|
+
/* Generate the data sent in the POST request */
|
249
|
+
requestData: function () {
|
250
|
+
'use strict';
|
251
|
+
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
252
|
+
var csrf_token = jQuery('meta[name=csrf-token]').attr('content'),
|
253
|
+
csrf_param = jQuery('meta[name=csrf-param]').attr('content');
|
254
|
+
|
255
|
+
var data = "_method=" + BestInPlaceEditor.defaults.ajaxMethod;
|
256
|
+
data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
|
257
|
+
|
258
|
+
if (csrf_param !== undefined && csrf_token !== undefined) {
|
259
|
+
data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
|
260
|
+
}
|
261
|
+
return data;
|
262
|
+
},
|
263
|
+
|
264
|
+
ajax: function (options) {
|
265
|
+
'use strict';
|
266
|
+
options.url = this.url;
|
267
|
+
options.beforeSend = function (xhr) {
|
268
|
+
xhr.setRequestHeader("Accept", "application/json");
|
269
|
+
};
|
270
|
+
return jQuery.ajax(options);
|
271
|
+
},
|
272
|
+
|
273
|
+
// Handlers ////////////////////////////////////////////////////////////////
|
274
|
+
|
275
|
+
loadSuccessCallback: function (data, status, xhr) {
|
276
|
+
'use strict';
|
277
|
+
data = jQuery.trim(data);
|
278
|
+
//Update original content with current text.
|
279
|
+
if (this.display_raw) {
|
280
|
+
this.original_content = this.element.html();
|
281
|
+
} else {
|
282
|
+
this.original_content = this.element.text();
|
283
|
+
}
|
284
|
+
|
285
|
+
if (data && data !== "") {
|
286
|
+
var response = jQuery.parseJSON(data);
|
287
|
+
if (response !== null && response.hasOwnProperty("display_as")) {
|
288
|
+
this.element.data('bip-original-content', this.element.text());
|
289
|
+
this.element.html(response.display_as);
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
293
|
+
this.element.trigger(jQuery.Event("best_in_place:success"), [data, status, xhr]);
|
294
|
+
this.element.trigger(jQuery.Event("ajax:success"), [data, status, xhr]);
|
295
|
+
|
296
|
+
// Binding back after being clicked
|
297
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
298
|
+
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
299
|
+
|
300
|
+
if (this.collectionValue !== null && this.formType === "select") {
|
301
|
+
this.collectionValue = this.previousCollectionValue;
|
302
|
+
this.previousCollectionValue = null;
|
303
|
+
}
|
304
|
+
},
|
305
|
+
|
306
|
+
loadErrorCallback: function (request, error) {
|
307
|
+
'use strict';
|
308
|
+
this.activateText(this.oldValue);
|
309
|
+
|
310
|
+
this.element.trigger(jQuery.Event("best_in_place:error"), [request, error]);
|
311
|
+
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
312
|
+
|
313
|
+
// Binding back after being clicked
|
314
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
315
|
+
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
316
|
+
},
|
317
|
+
|
318
|
+
clickHandler: function (event) {
|
319
|
+
'use strict';
|
320
|
+
event.preventDefault();
|
321
|
+
event.data.editor.activate();
|
322
|
+
},
|
323
|
+
|
324
|
+
setHtmlAttributes: function () {
|
325
|
+
'use strict';
|
326
|
+
var formField = this.element.find(this.formType);
|
327
|
+
|
328
|
+
if (this.html_attrs) {
|
329
|
+
var attrs = this.html_attrs;
|
330
|
+
$.each(attrs, function (key, val) {
|
331
|
+
formField.attr(key, val);
|
332
|
+
});
|
333
|
+
}
|
334
|
+
},
|
335
|
+
|
336
|
+
placeButtons: function (output, field) {
|
337
|
+
'use strict';
|
338
|
+
if (field.okButton) {
|
339
|
+
output.append(
|
340
|
+
jQuery(document.createElement('input'))
|
341
|
+
.attr('type', 'submit')
|
342
|
+
.attr('class', field.okButtonClass)
|
343
|
+
.attr('value', field.okButton)
|
344
|
+
);
|
345
|
+
}
|
346
|
+
if (field.cancelButton) {
|
347
|
+
output.append(
|
348
|
+
jQuery(document.createElement('input'))
|
349
|
+
.attr('type', 'button')
|
350
|
+
.attr('class', field.cancelButtonClass)
|
351
|
+
.attr('value', field.cancelButton)
|
352
|
+
);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
};
|
356
|
+
|
357
|
+
|
358
|
+
// Button cases:
|
359
|
+
// If no buttons, then blur saves, ESC cancels
|
360
|
+
// If just Cancel button, then blur saves, ESC or clicking Cancel cancels (careful of blur event!)
|
361
|
+
// If just OK button, then clicking OK saves (careful of blur event!), ESC or blur cancels
|
362
|
+
// If both buttons, then clicking OK saves, ESC or clicking Cancel or blur cancels
|
363
|
+
BestInPlaceEditor.forms = {
|
364
|
+
"input": {
|
365
|
+
activateForm: function () {
|
366
|
+
'use strict';
|
367
|
+
var output = jQuery(document.createElement('form'))
|
368
|
+
.addClass('form_in_place')
|
369
|
+
.attr('action', 'javascript:void(0);')
|
370
|
+
.attr('style', 'display:inline');
|
371
|
+
var input_elt = jQuery(document.createElement('input'))
|
372
|
+
.attr('type', 'text')
|
373
|
+
.attr('name', this.attributeName)
|
374
|
+
.val(this.display_value);
|
375
|
+
|
376
|
+
// Add class to form input
|
377
|
+
if (this.inner_class) {
|
378
|
+
input_elt.addClass(this.inner_class);
|
379
|
+
}
|
380
|
+
|
381
|
+
output.append(input_elt);
|
382
|
+
this.placeButtons(output, this);
|
383
|
+
|
384
|
+
this.element.html(output);
|
385
|
+
this.setHtmlAttributes();
|
386
|
+
|
387
|
+
this.element.find("input[type='text']")[0].select();
|
388
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
389
|
+
if (this.cancelButton) {
|
390
|
+
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
|
391
|
+
}
|
392
|
+
if (!this.okButton) {
|
393
|
+
this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
394
|
+
}
|
395
|
+
this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
396
|
+
this.blurTimer = null;
|
397
|
+
this.userClicked = false;
|
398
|
+
},
|
399
|
+
|
400
|
+
getValue: function () {
|
401
|
+
'use strict';
|
402
|
+
return this.sanitizeValue(this.element.find("input").val());
|
403
|
+
},
|
404
|
+
|
405
|
+
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
406
|
+
inputBlurHandler: function (event) {
|
407
|
+
'use strict';
|
408
|
+
if (event.data.editor.okButton) {
|
409
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
410
|
+
if (!event.data.editor.userClicked) {
|
411
|
+
event.data.editor.abort();
|
412
|
+
}
|
413
|
+
}, 500);
|
414
|
+
} else {
|
415
|
+
if (event.data.editor.cancelButton) {
|
416
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
417
|
+
if (!event.data.editor.userClicked) {
|
418
|
+
event.data.editor.update();
|
419
|
+
}
|
420
|
+
}, 500);
|
421
|
+
} else {
|
422
|
+
event.data.editor.update();
|
423
|
+
}
|
424
|
+
}
|
425
|
+
},
|
426
|
+
|
427
|
+
submitHandler: function (event) {
|
428
|
+
'use strict';
|
429
|
+
event.data.editor.userClicked = true;
|
430
|
+
clearTimeout(event.data.editor.blurTimer);
|
431
|
+
event.data.editor.update();
|
432
|
+
},
|
433
|
+
|
434
|
+
cancelButtonHandler: function (event) {
|
435
|
+
'use strict';
|
436
|
+
event.data.editor.userClicked = true;
|
437
|
+
clearTimeout(event.data.editor.blurTimer);
|
438
|
+
event.data.editor.abort();
|
439
|
+
event.stopPropagation(); // Without this, click isn't handled
|
440
|
+
},
|
441
|
+
|
442
|
+
keyupHandler: function (event) {
|
443
|
+
'use strict';
|
444
|
+
if (event.keyCode === 27) {
|
445
|
+
event.data.editor.abort();
|
446
|
+
event.stopImmediatePropagation();
|
447
|
+
}
|
448
|
+
}
|
449
|
+
},
|
450
|
+
|
451
|
+
"select": {
|
452
|
+
activateForm: function () {
|
453
|
+
'use strict';
|
454
|
+
var output = jQuery(document.createElement('form'))
|
455
|
+
.attr('action', 'javascript:void(0)')
|
456
|
+
.attr('style', 'display:inline'),
|
457
|
+
selected = '',
|
458
|
+
select_elt = jQuery(document.createElement('select'))
|
459
|
+
.attr('class', this.inner_class !== null ? this.inner_class : ''),
|
460
|
+
currentCollectionValue = this.collectionValue,
|
461
|
+
key, value,
|
462
|
+
a = this.values;
|
463
|
+
|
464
|
+
$.each(a, function(index, arr){
|
465
|
+
key = arr[0];
|
466
|
+
value = arr[1];
|
467
|
+
var option_elt = jQuery(document.createElement('option'))
|
468
|
+
.val(key)
|
469
|
+
.html(value);
|
470
|
+
if (String(key) === String(currentCollectionValue)) option_elt.attr('selected', 'selected');
|
471
|
+
select_elt.append(option_elt);
|
472
|
+
});
|
473
|
+
output.append(select_elt);
|
474
|
+
|
475
|
+
this.element.html(output);
|
476
|
+
this.setHtmlAttributes();
|
477
|
+
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
478
|
+
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
479
|
+
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
480
|
+
this.element.find("select")[0].focus();
|
481
|
+
|
482
|
+
// automatically click on the select so you
|
483
|
+
// don't have to click twice
|
484
|
+
try {
|
485
|
+
var e = document.createEvent("MouseEvents");
|
486
|
+
e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
487
|
+
this.element.find("select")[0].dispatchEvent(e);
|
488
|
+
}
|
489
|
+
catch(e) {
|
490
|
+
// browser doesn't support this, e.g. IE8
|
491
|
+
}
|
492
|
+
},
|
493
|
+
|
494
|
+
getValue: function () {
|
495
|
+
'use strict';
|
496
|
+
return this.sanitizeValue(this.element.find("select").val());
|
497
|
+
},
|
498
|
+
|
499
|
+
blurHandler: function (event) {
|
500
|
+
'use strict';
|
501
|
+
event.data.editor.update();
|
502
|
+
},
|
503
|
+
|
504
|
+
keyupHandler: function (event) {
|
505
|
+
'use strict';
|
506
|
+
if (event.keyCode === 27) {
|
507
|
+
event.data.editor.abort();
|
508
|
+
}
|
509
|
+
}
|
510
|
+
},
|
511
|
+
|
512
|
+
"checkbox": {
|
513
|
+
activateForm: function () {
|
514
|
+
'use strict';
|
515
|
+
this.collectionValue = !this.getValue();
|
516
|
+
this.setHtmlAttributes();
|
517
|
+
this.update();
|
518
|
+
},
|
519
|
+
|
520
|
+
getValue: function () {
|
521
|
+
'use strict';
|
522
|
+
return this.collectionValue;
|
523
|
+
}
|
524
|
+
},
|
525
|
+
|
526
|
+
"textarea": {
|
527
|
+
activateForm: function () {
|
528
|
+
'use strict';
|
529
|
+
// grab width and height of text
|
530
|
+
var width = this.element.css('width');
|
531
|
+
var height = this.element.css('height');
|
532
|
+
|
533
|
+
// construct form
|
534
|
+
var output = jQuery(document.createElement('form'))
|
535
|
+
.addClass('form_in_place')
|
536
|
+
.attr('action', 'javascript:void(0);')
|
537
|
+
.attr('style', 'display:inline');
|
538
|
+
var textarea_elt = jQuery(document.createElement('textarea'))
|
539
|
+
.attr('name', this.attributeName)
|
540
|
+
.val(this.sanitizeValue(this.display_value));
|
541
|
+
|
542
|
+
if (this.inner_class !== null) {
|
543
|
+
textarea_elt.addClass(this.inner_class);
|
544
|
+
}
|
545
|
+
|
546
|
+
output.append(textarea_elt);
|
547
|
+
|
548
|
+
this.placeButtons(output, this);
|
549
|
+
|
550
|
+
this.element.html(output);
|
551
|
+
this.setHtmlAttributes();
|
552
|
+
|
553
|
+
// set width and height of textarea
|
554
|
+
jQuery(this.element.find("textarea")[0]).css({'min-width': width, 'min-height': height});
|
555
|
+
jQuery(this.element.find("textarea")[0]).autosize();
|
556
|
+
|
557
|
+
this.element.find("textarea")[0].focus();
|
558
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
|
559
|
+
|
560
|
+
if (this.cancelButton) {
|
561
|
+
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
|
562
|
+
}
|
563
|
+
|
564
|
+
if (!this.skipBlur) {
|
565
|
+
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
566
|
+
}
|
567
|
+
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
568
|
+
this.blurTimer = null;
|
569
|
+
this.userClicked = false;
|
570
|
+
},
|
571
|
+
|
572
|
+
getValue: function () {
|
573
|
+
'use strict';
|
574
|
+
return this.sanitizeValue(this.element.find("textarea").val());
|
575
|
+
},
|
576
|
+
|
577
|
+
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
578
|
+
blurHandler: function (event) {
|
579
|
+
'use strict';
|
580
|
+
if (event.data.editor.okButton) {
|
581
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
582
|
+
if (!event.data.editor.userClicked) {
|
583
|
+
event.data.editor.abortIfConfirm();
|
584
|
+
}
|
585
|
+
}, 500);
|
586
|
+
} else {
|
587
|
+
if (event.data.editor.cancelButton) {
|
588
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
589
|
+
if (!event.data.editor.userClicked) {
|
590
|
+
event.data.editor.update();
|
591
|
+
}
|
592
|
+
}, 500);
|
593
|
+
} else {
|
594
|
+
event.data.editor.update();
|
595
|
+
}
|
596
|
+
}
|
597
|
+
},
|
598
|
+
|
599
|
+
submitHandler: function (event) {
|
600
|
+
'use strict';
|
601
|
+
event.data.editor.userClicked = true;
|
602
|
+
clearTimeout(event.data.editor.blurTimer);
|
603
|
+
event.data.editor.update();
|
604
|
+
},
|
605
|
+
|
606
|
+
cancelButtonHandler: function (event) {
|
607
|
+
'use strict';
|
608
|
+
event.data.editor.userClicked = true;
|
609
|
+
clearTimeout(event.data.editor.blurTimer);
|
610
|
+
event.data.editor.abortIfConfirm();
|
611
|
+
event.stopPropagation(); // Without this, click isn't handled
|
612
|
+
},
|
613
|
+
|
614
|
+
keyupHandler: function (event) {
|
615
|
+
'use strict';
|
616
|
+
if (event.keyCode === 27) {
|
617
|
+
event.data.editor.abortIfConfirm();
|
618
|
+
}
|
619
|
+
}
|
620
|
+
}
|
621
|
+
};
|
622
|
+
|
623
|
+
BestInPlaceEditor.defaults = {
|
624
|
+
locales: {},
|
625
|
+
ajaxMethod: "put", //TODO Change to patch when support to 3.2 is dropped
|
626
|
+
ajaxDataType: 'text',
|
627
|
+
okButtonClass: '',
|
628
|
+
cancelButtonClass: '',
|
629
|
+
skipBlur: false
|
630
|
+
};
|
631
|
+
|
632
|
+
// Default locale
|
633
|
+
BestInPlaceEditor.defaults.locales[''] = {
|
634
|
+
confirmMessage: "Are you sure you want to discard your changes?",
|
635
|
+
uninitializedForm: "The form was not properly initialized. getValue is unbound",
|
636
|
+
placeHolder: '-'
|
637
|
+
};
|
638
|
+
|
639
|
+
jQuery.fn.best_in_place = function () {
|
640
|
+
'use strict';
|
641
|
+
function setBestInPlace(element) {
|
642
|
+
if (!element.data('bestInPlaceEditor')) {
|
643
|
+
element.data('bestInPlaceEditor', new BestInPlaceEditor(element));
|
644
|
+
return true;
|
645
|
+
}
|
646
|
+
}
|
647
|
+
|
648
|
+
jQuery(this.context).delegate(this.selector, 'click', function () {
|
649
|
+
var el = jQuery(this);
|
650
|
+
if (setBestInPlace(el)) {
|
651
|
+
el.click();
|
652
|
+
}
|
653
|
+
});
|
654
|
+
|
655
|
+
this.each(function () {
|
656
|
+
setBestInPlace(jQuery(this));
|
657
|
+
});
|
658
|
+
|
659
|
+
return this;
|
660
|
+
};
|
661
|
+
|
662
|
+
|
663
|
+
|