best_in_place 0.2.3 → 1.0.0
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/.travis.yml +5 -0
- data/Gemfile +1 -0
- data/best_in_place.gemspec +2 -1
- data/{test_app/public → lib/assets}/javascripts/best_in_place.js +1 -3
- data/{public → lib/assets}/javascripts/jquery.purr.js +0 -0
- data/lib/best_in_place.rb +1 -3
- data/lib/best_in_place/engine.rb +7 -0
- data/lib/best_in_place/helper.rb +1 -2
- data/lib/best_in_place/test_helpers.rb +8 -21
- data/lib/best_in_place/version.rb +1 -1
- data/spec/helpers/best_in_place_spec.rb +2 -12
- data/spec/integration/double_init_spec.rb +2 -2
- data/spec/integration/js_spec.rb +12 -12
- data/test_app/Gemfile +10 -3
- data/test_app/{public → app/assets}/images/red_pen.png +0 -0
- data/test_app/{public → app/assets}/javascripts/application.js +3 -2
- data/test_app/{public → app/assets}/stylesheets/.gitkeep +0 -0
- data/test_app/{public → app/assets}/stylesheets/scaffold.css +0 -0
- data/test_app/{public → app/assets}/stylesheets/style.css +0 -0
- data/test_app/app/views/layouts/application.html.erb +1 -1
- data/test_app/config/application.rb +12 -3
- metadata +32 -29
- data/lib/best_in_place/utils.rb +0 -15
- data/lib/generators/best_in_place/setup_generator.rb +0 -11
- data/public/javascripts/best_in_place.js +0 -481
- data/public/javascripts/jquery-1.4.4.js +0 -7179
- data/spec/integration/text_area_spec.rb +0 -30
- data/test_app/public/images/rails.png +0 -0
- data/test_app/public/javascripts/jquery-1.4.4.min.js +0 -167
- data/test_app/public/javascripts/jquery.purr.js +0 -161
- data/test_app/public/javascripts/rails.js +0 -148
data/lib/best_in_place/utils.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module BestInPlace
|
2
|
-
class Utils
|
3
|
-
|
4
|
-
def self.build_best_in_place_id(object, field)
|
5
|
-
if object.is_a?(Symbol) || object.is_a?(String)
|
6
|
-
return "best_in_place_#{object}_#{field}"
|
7
|
-
end
|
8
|
-
|
9
|
-
id = "best_in_place_#{object.class.to_s.demodulize.underscore}"
|
10
|
-
id << "_#{object.id}" if object.class.ancestors.include?(ActiveRecord::Base)
|
11
|
-
id << "_#{field}"
|
12
|
-
id
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module BestInPlace
|
2
|
-
|
3
|
-
class SetupGenerator < Rails::Generators::Base
|
4
|
-
source_root File.expand_path("../../../../public/javascripts", __FILE__)
|
5
|
-
desc "Copies best_in_place.js to the /public/javascripts folder of your app."
|
6
|
-
|
7
|
-
def copy_js
|
8
|
-
copy_file "best_in_place.js", "public/javascripts/best_in_place.js"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,481 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
BestInPlace (for jQuery)
|
3
|
-
version: 0.1.0 (01/01/2011)
|
4
|
-
@requires jQuery >= v1.4
|
5
|
-
@requires jQuery.purr to display pop-up windows
|
6
|
-
|
7
|
-
By Bernat Farrero based on the work of Jan Varwig.
|
8
|
-
Examples at http://bernatfarrero.com
|
9
|
-
|
10
|
-
Licensed under the MIT:
|
11
|
-
http://www.opensource.org/licenses/mit-license.php
|
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
|
-
function BestInPlaceEditor(e) {
|
23
|
-
this.element = jQuery(e);
|
24
|
-
this.initOptions();
|
25
|
-
this.bindForm();
|
26
|
-
this.initNil();
|
27
|
-
$(this.activator).bind('click', {editor: this}, this.clickHandler);
|
28
|
-
}
|
29
|
-
|
30
|
-
BestInPlaceEditor.prototype = {
|
31
|
-
// Public Interface Functions //////////////////////////////////////////////
|
32
|
-
|
33
|
-
activate : function() {
|
34
|
-
var elem = this.isNil ? "" : this.element.html();
|
35
|
-
this.oldValue = elem;
|
36
|
-
$(this.activator).unbind("click", this.clickHandler);
|
37
|
-
this.activateForm();
|
38
|
-
},
|
39
|
-
|
40
|
-
abort : function() {
|
41
|
-
if (this.isNil) this.element.html(this.nil);
|
42
|
-
else this.element.html(this.oldValue);
|
43
|
-
$(this.activator).bind('click', {editor: this}, this.clickHandler);
|
44
|
-
},
|
45
|
-
|
46
|
-
update : function() {
|
47
|
-
var editor = this;
|
48
|
-
if (this.formType in {"input":1, "textarea":1} && this.getValue() == this.oldValue)
|
49
|
-
{ // Avoid request if no change is made
|
50
|
-
this.abort();
|
51
|
-
return true;
|
52
|
-
}
|
53
|
-
this.isNil = false;
|
54
|
-
editor.ajax({
|
55
|
-
"type" : "post",
|
56
|
-
"dataType" : "text",
|
57
|
-
"data" : editor.requestData(),
|
58
|
-
"success" : function(data){ editor.loadSuccessCallback(data); },
|
59
|
-
"error" : function(request, error){ editor.loadErrorCallback(request, error); }
|
60
|
-
});
|
61
|
-
if (this.formType == "select") {
|
62
|
-
var value = this.getValue();
|
63
|
-
$.each(this.values, function(i, v) {
|
64
|
-
if (value == v[0]) {
|
65
|
-
editor.element.html(v[1]);
|
66
|
-
}
|
67
|
-
}
|
68
|
-
);
|
69
|
-
} else if (this.formType == "checkbox") {
|
70
|
-
editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
|
71
|
-
} else {
|
72
|
-
editor.element.html(this.getValue() != "" ? this.getValue() : this.nil);
|
73
|
-
}
|
74
|
-
},
|
75
|
-
|
76
|
-
activateForm : function() {
|
77
|
-
alert("The form was not properly initialized. activateForm is unbound");
|
78
|
-
},
|
79
|
-
|
80
|
-
// Helper Functions ////////////////////////////////////////////////////////
|
81
|
-
|
82
|
-
initOptions : function() {
|
83
|
-
// Try parent supplied info
|
84
|
-
var self = this;
|
85
|
-
self.element.parents().each(function(){
|
86
|
-
self.url = self.url || jQuery(this).attr("data-url");
|
87
|
-
self.collection = self.collection || jQuery(this).attr("data-collection");
|
88
|
-
self.formType = self.formType || jQuery(this).attr("data-type");
|
89
|
-
self.objectName = self.objectName || jQuery(this).attr("data-object");
|
90
|
-
self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
|
91
|
-
self.nil = self.nil || jQuery(this).attr("data-nil");
|
92
|
-
self.inner_class = self.inner_class || jQuery(this).attr("data-inner-class");
|
93
|
-
self.html_attrs = self.html_attrs || jQuery(this).attr("data-html-attrs");
|
94
|
-
});
|
95
|
-
|
96
|
-
// Try Rails-id based if parents did not explicitly supply something
|
97
|
-
self.element.parents().each(function(){
|
98
|
-
var res = this.id.match(/^(\w+)_(\d+)$/i);
|
99
|
-
if (res) {
|
100
|
-
self.objectName = self.objectName || res[1];
|
101
|
-
}
|
102
|
-
});
|
103
|
-
|
104
|
-
// Load own attributes (overrides all others)
|
105
|
-
self.url = self.element.attr("data-url") || self.url || document.location.pathname;
|
106
|
-
self.collection = self.element.attr("data-collection") || self.collection;
|
107
|
-
self.formType = self.element.attr("data-type") || self.formtype || "input";
|
108
|
-
self.objectName = self.element.attr("data-object") || self.objectName;
|
109
|
-
self.attributeName = self.element.attr("data-attribute") || self.attributeName;
|
110
|
-
self.activator = self.element.attr("data-activator") || self.element;
|
111
|
-
self.nil = self.element.attr("data-nil") || self.nil || "-";
|
112
|
-
self.inner_class = self.element.attr("data-inner-class") || self.inner_class || null;
|
113
|
-
self.html_attrs = self.element.attr("data-html-attrs") || self.html_attrs;
|
114
|
-
|
115
|
-
if (!self.element.attr("data-sanitize")) {
|
116
|
-
self.sanitize = true;
|
117
|
-
}
|
118
|
-
else {
|
119
|
-
self.sanitize = (self.element.attr("data-sanitize") == "true");
|
120
|
-
}
|
121
|
-
|
122
|
-
if ((self.formType == "select" || self.formType == "checkbox") && self.collection !== null)
|
123
|
-
{
|
124
|
-
self.values = jQuery.parseJSON(self.collection);
|
125
|
-
}
|
126
|
-
},
|
127
|
-
|
128
|
-
bindForm : function() {
|
129
|
-
this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
|
130
|
-
this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
|
131
|
-
},
|
132
|
-
|
133
|
-
initNil: function() {
|
134
|
-
if (this.element.html() == "")
|
135
|
-
{
|
136
|
-
this.isNil = true
|
137
|
-
this.element.html(this.nil)
|
138
|
-
}
|
139
|
-
},
|
140
|
-
|
141
|
-
getValue : function() {
|
142
|
-
alert("The form was not properly initialized. getValue is unbound");
|
143
|
-
},
|
144
|
-
|
145
|
-
// Trim and Strips HTML from text
|
146
|
-
sanitizeValue : function(s) {
|
147
|
-
if (this.sanitize)
|
148
|
-
{
|
149
|
-
var tmp = document.createElement("DIV");
|
150
|
-
tmp.innerHTML = s;
|
151
|
-
s = tmp.textContent || tmp.innerText;
|
152
|
-
}
|
153
|
-
return jQuery.trim(s);
|
154
|
-
},
|
155
|
-
|
156
|
-
/* Generate the data sent in the POST request */
|
157
|
-
requestData : function() {
|
158
|
-
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
159
|
-
csrf_token = $('meta[name=csrf-token]').attr('content');
|
160
|
-
csrf_param = $('meta[name=csrf-param]').attr('content');
|
161
|
-
|
162
|
-
var data = "_method=put";
|
163
|
-
data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
|
164
|
-
|
165
|
-
if (csrf_param !== undefined && csrf_token !== undefined) {
|
166
|
-
data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
|
167
|
-
}
|
168
|
-
return data;
|
169
|
-
},
|
170
|
-
|
171
|
-
ajax : function(options) {
|
172
|
-
options.url = this.url;
|
173
|
-
options.beforeSend = function(xhr){ xhr.setRequestHeader("Accept", "application/json"); };
|
174
|
-
return jQuery.ajax(options);
|
175
|
-
},
|
176
|
-
|
177
|
-
// Handlers ////////////////////////////////////////////////////////////////
|
178
|
-
|
179
|
-
loadSuccessCallback : function(data) {
|
180
|
-
this.element.html(data[this.objectName]);
|
181
|
-
this.element.trigger($.Event("ajax:success"), data);
|
182
|
-
|
183
|
-
// Binding back after being clicked
|
184
|
-
$(this.activator).bind('click', {editor: this}, this.clickHandler);
|
185
|
-
},
|
186
|
-
|
187
|
-
loadErrorCallback : function(request, error) {
|
188
|
-
this.element.html(this.oldValue);
|
189
|
-
|
190
|
-
// Display all error messages from server side validation
|
191
|
-
$.each(jQuery.parseJSON(request.responseText), function(index, value) {
|
192
|
-
if( typeof(value) == "object") {value = index + " " + value.toString(); }
|
193
|
-
var container = $("<span class='flash-error'></span>").html(value);
|
194
|
-
container.purr();
|
195
|
-
});
|
196
|
-
|
197
|
-
// Binding back after being clicked
|
198
|
-
$(this.activator).bind('click', {editor: this}, this.clickHandler);
|
199
|
-
},
|
200
|
-
|
201
|
-
clickHandler : function(event) {
|
202
|
-
event.data.editor.activate();
|
203
|
-
},
|
204
|
-
|
205
|
-
setHtmlAttributes : function() {
|
206
|
-
var formField = this.element.find(this.formType);
|
207
|
-
var attrs = jQuery.parseJSON(this.html_attrs);
|
208
|
-
for(var key in attrs){
|
209
|
-
formField.attr(key, attrs[key]);
|
210
|
-
}
|
211
|
-
}
|
212
|
-
};
|
213
|
-
|
214
|
-
|
215
|
-
BestInPlaceEditor.forms = {
|
216
|
-
"input" : {
|
217
|
-
activateForm : function() {
|
218
|
-
var output = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;">';
|
219
|
-
output += '<input type="text" name="'+ this.attributeName + '" value="' + this.sanitizeValue(this.oldValue) + '"';
|
220
|
-
if (this.inner_class != null) {
|
221
|
-
output += ' class="' + this.inner_class + '"';
|
222
|
-
}
|
223
|
-
output += '></form>'
|
224
|
-
this.element.html(output);
|
225
|
-
this.setHtmlAttributes();
|
226
|
-
this.element.find('input')[0].select();
|
227
|
-
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
228
|
-
this.element.find("input").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
229
|
-
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
230
|
-
},
|
231
|
-
|
232
|
-
getValue : function() {
|
233
|
-
return this.sanitizeValue(this.element.find("input").val());
|
234
|
-
},
|
235
|
-
|
236
|
-
inputBlurHandler : function(event) {
|
237
|
-
event.data.editor.update();
|
238
|
-
},
|
239
|
-
|
240
|
-
submitHandler : function(event) {
|
241
|
-
event.data.editor.update();
|
242
|
-
},
|
243
|
-
|
244
|
-
keyupHandler : function(event) {
|
245
|
-
if (event.keyCode == 27) {
|
246
|
-
event.data.editor.abort();
|
247
|
-
}
|
248
|
-
}
|
249
|
-
},
|
250
|
-
|
251
|
-
"select" : {
|
252
|
-
activateForm : function() {
|
253
|
-
var output = "<form action='javascript:void(0)' style='display:inline;'><select>";
|
254
|
-
var selected = "";
|
255
|
-
var oldValue = this.oldValue;
|
256
|
-
$.each(this.values, function(index, value) {
|
257
|
-
selected = (value[1] == oldValue ? "selected='selected'" : "");
|
258
|
-
output += "<option value='" + value[0] + "' " + selected + ">" + value[1] + "</option>";
|
259
|
-
});
|
260
|
-
output += "</select></form>";
|
261
|
-
this.element.html(output);
|
262
|
-
this.setHtmlAttributes();
|
263
|
-
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
264
|
-
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
265
|
-
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
266
|
-
this.element.find("select")[0].focus();
|
267
|
-
},
|
268
|
-
|
269
|
-
getValue : function() {
|
270
|
-
return this.sanitizeValue(this.element.find("select").val());
|
271
|
-
},
|
272
|
-
|
273
|
-
blurHandler : function(event) {
|
274
|
-
event.data.editor.update();
|
275
|
-
},
|
276
|
-
|
277
|
-
keyupHandler : function(event) {
|
278
|
-
if (event.keyCode == 27) event.data.editor.abort();
|
279
|
-
}
|
280
|
-
},
|
281
|
-
|
282
|
-
"checkbox" : {
|
283
|
-
activateForm : function() {
|
284
|
-
var newValue = Boolean(this.oldValue != this.values[1]);
|
285
|
-
var output = newValue ? this.values[1] : this.values[0];
|
286
|
-
this.element.html(output);
|
287
|
-
this.setHtmlAttributes();
|
288
|
-
this.update();
|
289
|
-
},
|
290
|
-
|
291
|
-
getValue : function() {
|
292
|
-
return Boolean(this.element.html() == this.values[1]);
|
293
|
-
}
|
294
|
-
},
|
295
|
-
|
296
|
-
"textarea" : {
|
297
|
-
activateForm : function() {
|
298
|
-
// grab width and height of text
|
299
|
-
width = this.element.css('width');
|
300
|
-
height = this.element.css('height');
|
301
|
-
|
302
|
-
// construct the form
|
303
|
-
var output = '<form action="javascript:void(0)" style="display:inline;"><textarea>';
|
304
|
-
output += this.sanitizeValue(this.oldValue);
|
305
|
-
output += '</textarea></form>';
|
306
|
-
this.element.html(output);
|
307
|
-
this.setHtmlAttributes();
|
308
|
-
|
309
|
-
// set width and height of textarea
|
310
|
-
jQuery(this.element.find("textarea")[0]).css({ 'min-width': width, 'min-height': height });
|
311
|
-
jQuery(this.element.find("textarea")[0]).elastic();
|
312
|
-
|
313
|
-
this.element.find("textarea")[0].focus();
|
314
|
-
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
315
|
-
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
316
|
-
},
|
317
|
-
|
318
|
-
getValue : function() {
|
319
|
-
return this.sanitizeValue(this.element.find("textarea").val());
|
320
|
-
},
|
321
|
-
|
322
|
-
blurHandler : function(event) {
|
323
|
-
event.data.editor.update();
|
324
|
-
},
|
325
|
-
|
326
|
-
keyupHandler : function(event) {
|
327
|
-
if (event.keyCode == 27) {
|
328
|
-
BestInPlaceEditor.forms.textarea.abort(event.data.editor);
|
329
|
-
}
|
330
|
-
},
|
331
|
-
|
332
|
-
abort : function(editor) {
|
333
|
-
if (confirm("Are you sure you want to discard your changes?")) {
|
334
|
-
editor.abort();
|
335
|
-
}
|
336
|
-
}
|
337
|
-
}
|
338
|
-
};
|
339
|
-
|
340
|
-
jQuery.fn.best_in_place = function() {
|
341
|
-
this.each(function(){
|
342
|
-
if (!jQuery(this).data('bestInPlaceEditor')) {
|
343
|
-
jQuery(this).data('bestInPlaceEditor', new BestInPlaceEditor(this));
|
344
|
-
}
|
345
|
-
});
|
346
|
-
return this;
|
347
|
-
};
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
/**
|
352
|
-
* @name Elastic
|
353
|
-
* @descripton Elastic is Jquery plugin that grow and shrink your textareas automaticliy
|
354
|
-
* @version 1.6.5
|
355
|
-
* @requires Jquery 1.2.6+
|
356
|
-
*
|
357
|
-
* @author Jan Jarfalk
|
358
|
-
* @author-email jan.jarfalk@unwrongest.com
|
359
|
-
* @author-website http://www.unwrongest.com
|
360
|
-
*
|
361
|
-
* @licens MIT License - http://www.opensource.org/licenses/mit-license.php
|
362
|
-
*/
|
363
|
-
|
364
|
-
(function(jQuery){
|
365
|
-
jQuery.fn.extend({
|
366
|
-
elastic: function() {
|
367
|
-
// We will create a div clone of the textarea
|
368
|
-
// by copying these attributes from the textarea to the div.
|
369
|
-
var mimics = [
|
370
|
-
'paddingTop',
|
371
|
-
'paddingRight',
|
372
|
-
'paddingBottom',
|
373
|
-
'paddingLeft',
|
374
|
-
'fontSize',
|
375
|
-
'lineHeight',
|
376
|
-
'fontFamily',
|
377
|
-
'width',
|
378
|
-
'fontWeight'];
|
379
|
-
|
380
|
-
return this.each( function() {
|
381
|
-
|
382
|
-
// Elastic only works on textareas
|
383
|
-
if ( this.type != 'textarea' ) {
|
384
|
-
return false;
|
385
|
-
}
|
386
|
-
|
387
|
-
var $textarea = jQuery(this),
|
388
|
-
$twin = jQuery('<div />').css({'position': 'absolute','display':'none','word-wrap':'break-word'}),
|
389
|
-
lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
|
390
|
-
minheight = parseInt($textarea.css('height'),10) || lineHeight*3,
|
391
|
-
maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
|
392
|
-
goalheight = 0,
|
393
|
-
i = 0;
|
394
|
-
|
395
|
-
// Opera returns max-height of -1 if not set
|
396
|
-
if (maxheight < 0) { maxheight = Number.MAX_VALUE; }
|
397
|
-
|
398
|
-
// Append the twin to the DOM
|
399
|
-
// We are going to meassure the height of this, not the textarea.
|
400
|
-
$twin.appendTo($textarea.parent());
|
401
|
-
|
402
|
-
// Copy the essential styles (mimics) from the textarea to the twin
|
403
|
-
var i = mimics.length;
|
404
|
-
while(i--){
|
405
|
-
$twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
|
406
|
-
}
|
407
|
-
|
408
|
-
|
409
|
-
// Sets a given height and overflow state on the textarea
|
410
|
-
function setHeightAndOverflow(height, overflow){
|
411
|
-
curratedHeight = Math.floor(parseInt(height,10));
|
412
|
-
if($textarea.height() != curratedHeight){
|
413
|
-
$textarea.css({'height': curratedHeight + 'px','overflow':overflow});
|
414
|
-
|
415
|
-
}
|
416
|
-
}
|
417
|
-
|
418
|
-
|
419
|
-
// This function will update the height of the textarea if necessary
|
420
|
-
function update() {
|
421
|
-
|
422
|
-
// Get curated content from the textarea.
|
423
|
-
var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ /g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
|
424
|
-
|
425
|
-
// Compare curated content with curated twin.
|
426
|
-
var twinContent = $twin.html().replace(/<br>/ig,'<br />');
|
427
|
-
|
428
|
-
if(textareaContent+' ' != twinContent){
|
429
|
-
|
430
|
-
// Add an extra white space so new rows are added when you are at the end of a row.
|
431
|
-
$twin.html(textareaContent+' ');
|
432
|
-
|
433
|
-
// Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
|
434
|
-
if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){
|
435
|
-
|
436
|
-
var goalheight = $twin.height()+lineHeight;
|
437
|
-
if(goalheight >= maxheight) {
|
438
|
-
setHeightAndOverflow(maxheight,'auto');
|
439
|
-
} else if(goalheight <= minheight) {
|
440
|
-
setHeightAndOverflow(minheight,'hidden');
|
441
|
-
} else {
|
442
|
-
setHeightAndOverflow(goalheight,'hidden');
|
443
|
-
}
|
444
|
-
|
445
|
-
}
|
446
|
-
|
447
|
-
}
|
448
|
-
|
449
|
-
}
|
450
|
-
|
451
|
-
// Hide scrollbars
|
452
|
-
$textarea.css({'overflow':'hidden'});
|
453
|
-
|
454
|
-
// Update textarea size on keyup, change, cut and paste
|
455
|
-
$textarea.bind('keyup change cut paste', function(){
|
456
|
-
update();
|
457
|
-
});
|
458
|
-
|
459
|
-
// Compact textarea on blur
|
460
|
-
// Lets animate this....
|
461
|
-
$textarea.bind('blur',function(){
|
462
|
-
if($twin.height() < maxheight){
|
463
|
-
if($twin.height() > minheight) {
|
464
|
-
$textarea.height($twin.height());
|
465
|
-
} else {
|
466
|
-
$textarea.height(minheight);
|
467
|
-
}
|
468
|
-
}
|
469
|
-
});
|
470
|
-
|
471
|
-
// And this line is to catch the browser paste event
|
472
|
-
$textarea.live('input paste',function(e){ setTimeout( update, 250); });
|
473
|
-
|
474
|
-
// Run update once when elastic is initialized
|
475
|
-
update();
|
476
|
-
|
477
|
-
});
|
478
|
-
|
479
|
-
}
|
480
|
-
});
|
481
|
-
})(jQuery);
|