best_in_place 2.1.0 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -5
- data/.rspec +1 -0
- data/.travis.yml +12 -5
- data/Appraisals +17 -0
- data/CHANGELOG.md +51 -30
- data/Gemfile +15 -2
- data/README.md +52 -105
- data/best_in_place.gemspec +13 -11
- data/config.ru +7 -0
- data/gemfiles/rails_3.2.gemfile +24 -0
- data/gemfiles/rails_4.0.gemfile +23 -0
- data/gemfiles/rails_4.1.gemfile +23 -0
- data/gemfiles/rails_edge.gemfile +25 -0
- data/lib/assets/javascripts/best_in_place.jquery-ui.js +57 -0
- data/lib/assets/javascripts/best_in_place.js +551 -650
- data/lib/assets/javascripts/best_in_place.purr.js +16 -6
- data/lib/best_in_place.rb +29 -9
- data/lib/best_in_place/controller_extensions.rb +10 -13
- data/lib/best_in_place/display_methods.rb +26 -21
- data/lib/best_in_place/engine.rb +2 -2
- data/lib/best_in_place/helper.rb +145 -87
- data/lib/best_in_place/railtie.rb +5 -2
- data/lib/best_in_place/test_helpers.rb +0 -1
- data/lib/best_in_place/utils.rb +20 -12
- data/lib/best_in_place/version.rb +1 -1
- data/spec/{helpers/best_in_place_spec.rb → helper_spec.rb} +134 -99
- data/spec/integration/double_init_spec.rb +3 -5
- data/spec/integration/js_spec.rb +193 -123
- data/spec/integration/live_spec.rb +3 -4
- data/spec/integration/text_area_spec.rb +4 -4
- data/spec/internal/app/assets/images/info.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/no.png +0 -0
- data/spec/internal/app/assets/images/purrBottom.png +0 -0
- data/spec/internal/app/assets/images/purrClose.png +0 -0
- data/spec/internal/app/assets/images/purrTop.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/red_pen.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-icons_222222_256x240.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-icons_228ef1_256x240.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-icons_ef8c08_256x240.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-icons_ffd27a_256x240.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/ui-icons_ffffff_256x240.png +0 -0
- data/{test_app → spec/internal}/app/assets/images/yes.png +0 -0
- data/spec/internal/app/assets/javascripts/application.js +37 -0
- data/{test_app → spec/internal}/app/assets/stylesheets/.gitkeep +0 -0
- data/{test_app → spec/internal}/app/assets/stylesheets/jquery-ui-1.8.16.custom.css.erb +1 -2
- data/{test_app → spec/internal}/app/assets/stylesheets/scaffold.css +1 -1
- data/{test_app → spec/internal}/app/assets/stylesheets/style.css.erb +2 -4
- data/{test_app → spec/internal}/app/controllers/admin/users_controller.rb +8 -3
- data/{test_app → spec/internal}/app/controllers/application_controller.rb +0 -0
- data/{test_app → spec/internal}/app/controllers/cuca/cars_controller.rb +0 -0
- data/{test_app → spec/internal}/app/controllers/users_controller.rb +8 -40
- data/{test_app → spec/internal}/app/helpers/application_helper.rb +0 -0
- data/spec/internal/app/helpers/users_helper.rb +29 -0
- data/{test_app → spec/internal}/app/models/cuca/car.rb +0 -0
- data/{test_app → spec/internal}/app/models/user.rb +5 -1
- data/{test_app → spec/internal}/app/views/admin/users/show.html.erb +2 -2
- data/{test_app → spec/internal}/app/views/cuca/cars/show.html.erb +0 -0
- data/{test_app → spec/internal}/app/views/layouts/application.html.erb +1 -1
- data/{test_app → spec/internal}/app/views/users/_form.html.erb +2 -2
- data/{test_app → spec/internal}/app/views/users/double_init.html.erb +4 -10
- data/spec/internal/app/views/users/edit.html.erb +5 -0
- data/{test_app → spec/internal}/app/views/users/email_field.html.erb +0 -0
- data/{test_app → spec/internal}/app/views/users/index.html.erb +0 -0
- data/{test_app → spec/internal}/app/views/users/new.html.erb +0 -0
- data/{test_app → spec/internal}/app/views/users/show.html.erb +32 -24
- data/{test_app → spec/internal}/app/views/users/show_ajax.html.erb +0 -0
- data/spec/internal/config/database.yml +5 -0
- data/{test_app → spec/internal}/config/initializers/countries.rb +0 -0
- data/{test_app → spec/internal}/config/initializers/default_date_format.rb +0 -0
- data/spec/internal/config/initializers/development.rb +8 -0
- data/{test_app → spec/internal}/config/routes.rb +1 -2
- data/spec/internal/db/schema.rb +26 -0
- data/{test_app → spec/internal}/public/favicon.ico +0 -0
- data/spec/rails_helper.rb +21 -0
- data/spec/support/retry_on_timeout.rb +4 -7
- data/spec/utils_spec.rb +21 -0
- data/vendor/assets/javascripts/jquery.autosize.js +272 -0
- data/{lib → vendor}/assets/javascripts/jquery.purr.js +1 -1
- metadata +92 -175
- data/lib/best_in_place/check_version.rb +0 -8
- data/spec/spec_helper.rb +0 -23
- data/test_app/Gemfile +0 -16
- data/test_app/README +0 -256
- data/test_app/Rakefile +0 -7
- data/test_app/app/assets/javascripts/application.js +0 -35
- data/test_app/app/helpers/users_helper.rb +0 -29
- data/test_app/config.ru +0 -4
- data/test_app/config/application.rb +0 -51
- data/test_app/config/boot.rb +0 -13
- data/test_app/config/database.yml +0 -22
- data/test_app/config/environment.rb +0 -5
- data/test_app/config/environments/development.rb +0 -25
- data/test_app/config/environments/production.rb +0 -49
- data/test_app/config/environments/test.rb +0 -35
- data/test_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test_app/config/initializers/inflections.rb +0 -10
- data/test_app/config/initializers/mime_types.rb +0 -5
- data/test_app/config/initializers/secret_token.rb +0 -7
- data/test_app/config/initializers/session_store.rb +0 -8
- data/test_app/config/locales/en.yml +0 -5
- data/test_app/db/migrate/20101206205922_create_users.rb +0 -18
- data/test_app/db/migrate/20101212170114_add_receive_email_to_user.rb +0 -9
- data/test_app/db/migrate/20110115204441_add_description_to_user.rb +0 -9
- data/test_app/db/migrate/20111210084202_add_favorite_color_to_users.rb +0 -5
- data/test_app/db/migrate/20111210084251_add_favorite_books_to_users.rb +0 -5
- data/test_app/db/migrate/20111217215935_add_birth_date_to_users.rb +0 -5
- data/test_app/db/migrate/20111224181356_add_money_to_user.rb +0 -5
- data/test_app/db/migrate/20120513003308_create_cars.rb +0 -11
- data/test_app/db/migrate/20120607172609_add_favorite_movie_to_users.rb +0 -5
- data/test_app/db/migrate/20120616170454_add_money_proc_to_users.rb +0 -6
- data/test_app/db/migrate/20120620165212_add_height_to_user.rb +0 -5
- data/test_app/db/migrate/20130213224102_add_favorite_locale_to_users.rb +0 -5
- data/test_app/db/schema.rb +0 -41
- data/test_app/db/seeds.rb +0 -19
- data/test_app/doc/README_FOR_APP +0 -2
- data/test_app/lib/tasks/.gitkeep +0 -0
- data/test_app/lib/tasks/cron.rake +0 -7
- data/test_app/public/404.html +0 -26
- data/test_app/public/422.html +0 -26
- data/test_app/public/500.html +0 -26
- data/test_app/public/robots.txt +0 -5
- data/test_app/script/rails +0 -6
- data/test_app/test/fixtures/users.yml +0 -17
- data/test_app/test/functional/users_controller_test.rb +0 -49
- data/test_app/test/performance/browsing_test.rb +0 -9
- data/test_app/test/test_helper.rb +0 -13
- data/test_app/test/unit/helpers/users_helper_test.rb +0 -4
- data/test_app/test/unit/user_test.rb +0 -8
- data/test_app/vendor/plugins/.gitkeep +0 -0
File without changes
|
File without changes
|
File without changes
|
@@ -7,19 +7,19 @@
|
|
7
7
|
<tr>
|
8
8
|
<td>Name <a id="editme" href="#">(edit me)</a></td>
|
9
9
|
<td id="name">
|
10
|
-
<%= best_in_place @user, :name, :
|
10
|
+
<%= best_in_place @user, :name, as: :input, :activator => "#editme" %>
|
11
11
|
</td>
|
12
12
|
</tr>
|
13
13
|
<tr>
|
14
14
|
<td>Last Name</td>
|
15
15
|
<td id="last_name">
|
16
|
-
<%= best_in_place @user, :last_name, :
|
16
|
+
<%= best_in_place @user, :last_name, place_holder: 'Nothing to show' %>
|
17
17
|
</td>
|
18
18
|
</tr>
|
19
19
|
<tr>
|
20
20
|
<td>Height</td>
|
21
21
|
<td id="height">
|
22
|
-
<%= best_in_place @user, :height, :
|
22
|
+
<%= best_in_place @user, :height, as: :select, :collection => height_collection, :raw => true %>
|
23
23
|
</td>
|
24
24
|
</tr>
|
25
25
|
<tr>
|
@@ -31,7 +31,7 @@
|
|
31
31
|
<tr>
|
32
32
|
<td>Birth date</td>
|
33
33
|
<td id="birth_date">
|
34
|
-
<%= best_in_place @user, :birth_date, :
|
34
|
+
<%= best_in_place @user, :birth_date, as: :date %>
|
35
35
|
</td>
|
36
36
|
</tr>
|
37
37
|
<tr>
|
@@ -43,46 +43,46 @@
|
|
43
43
|
<tr>
|
44
44
|
<td>ZIP</td>
|
45
45
|
<td id="zip">
|
46
|
-
<%= best_in_place @user, :zip %>
|
46
|
+
<%= best_in_place @user, :zip, :display_as => :zip_format %>
|
47
47
|
</td>
|
48
48
|
</tr>
|
49
49
|
<tr>
|
50
50
|
<td>Country</td>
|
51
51
|
<td id="country">
|
52
|
-
<%= best_in_place @user, :country, :
|
52
|
+
<%= best_in_place @user, :country, as: :select, :collection => @countries, :inner_class => :some_class %>
|
53
53
|
</td>
|
54
54
|
</tr>
|
55
55
|
<tr>
|
56
56
|
<td>Receive newsletter?</td>
|
57
57
|
<td id="receive_email">
|
58
|
-
<%= best_in_place @user, :receive_email, :
|
58
|
+
<%= best_in_place @user, :receive_email, as: :checkbox, collection: {'false' => "No thanks", 'true' => "Yes of course"} %>
|
59
59
|
</td>
|
60
60
|
</tr>
|
61
61
|
<tr>
|
62
62
|
<td>Receive newsletter (image)?</td>
|
63
63
|
<td id="receive_email_image">
|
64
|
-
<%= best_in_place @user, :receive_email, :
|
64
|
+
<%= best_in_place @user, :receive_email, as: :checkbox, :collection => {'false' => image_tag('no.png'), 'true' => image_tag('yes.png')} %>
|
65
65
|
</td>
|
66
66
|
</tr>
|
67
67
|
<tr>
|
68
68
|
<td>Favorite color</td>
|
69
69
|
<td id="favorite_color">
|
70
|
-
<%- opts = {
|
70
|
+
<%- opts = {:ok_button => 'Do it!', :cancel_button => 'Nope', :ok_button_class => 'custom-submit other-custom-submit', :cancel_button_class => 'custom-cancel other-custom-cancel'} %>
|
71
71
|
<%- opts.delete(:ok_button) if params[:suppress_ok_button] %>
|
72
|
-
<%- opts[:
|
72
|
+
<%- opts[:place_holder] = "<span class='placeholder'>Click to add your favorite color</span>" %>
|
73
73
|
<%= best_in_place @user, :favorite_color, opts %>
|
74
74
|
</td>
|
75
75
|
</tr>
|
76
76
|
<tr>
|
77
77
|
<td>Favorite locale</td>
|
78
78
|
<td id="favorite_locale">
|
79
|
-
<%= best_in_place @user, :favorite_locale, :
|
79
|
+
<%= best_in_place @user, :favorite_locale, place_holder: 'N/A' %>
|
80
80
|
</td>
|
81
81
|
</tr>
|
82
82
|
<tr>
|
83
83
|
<td>Favorite books</td>
|
84
84
|
<td id="favorite_books">
|
85
|
-
<%- opts = {
|
85
|
+
<%- opts = {as: :textarea, :ok_button => 'Save', :cancel_button => 'Cancel'} %>
|
86
86
|
<%- opts.delete(:ok_button) if params[:suppress_ok_button] %>
|
87
87
|
<%= best_in_place @user, :favorite_books, opts %>
|
88
88
|
</td>
|
@@ -90,13 +90,13 @@
|
|
90
90
|
<tr>
|
91
91
|
<td>User description</td>
|
92
92
|
<td id="description">
|
93
|
-
<%= best_in_place @user, :description, :display_as => :markdown_desc, :
|
93
|
+
<%= best_in_place @user, :description, :display_as => :markdown_desc, as: :textarea, :raw => true %>
|
94
94
|
</td>
|
95
95
|
</tr>
|
96
96
|
<tr>
|
97
97
|
<td>Simple-formatted user description</td>
|
98
98
|
<td id="dw_description">
|
99
|
-
<%= best_in_place @user, :description, :display_with => :simple_format, :
|
99
|
+
<%= best_in_place @user, :description, :display_with => :simple_format, as: :textarea %>
|
100
100
|
</td>
|
101
101
|
</tr>
|
102
102
|
<tr>
|
@@ -108,7 +108,7 @@
|
|
108
108
|
<tr>
|
109
109
|
<td>Money with proc</td>
|
110
110
|
<td id="money_proc">
|
111
|
-
<%= best_in_place @user, :money_proc, :display_with => lambda{ |v| v.blank? ? "No money" : number_to_currency(v) } %>
|
111
|
+
<%= best_in_place @user, :money_proc, :display_with => lambda { |v| v.blank? ? "No money" : number_to_currency(v) } %>
|
112
112
|
</td>
|
113
113
|
</tr>
|
114
114
|
<tr>
|
@@ -117,25 +117,33 @@
|
|
117
117
|
<%= best_in_place @user, :money_custom, :display_with => lambda { |x| bb(x) } %>
|
118
118
|
</td>
|
119
119
|
</tr>
|
120
|
+
<tr>
|
121
|
+
<td>Money with value</td>
|
122
|
+
<td id="money_value">
|
123
|
+
<%= best_in_place @user, :money, :display_with => :number_to_currency, value: 'Custom Value' %>
|
124
|
+
</td>
|
125
|
+
</tr>
|
120
126
|
<tr>
|
121
127
|
<td>Favorite Movie</td>
|
122
128
|
<td id="favorite_movie">
|
123
|
-
<%- opts = {
|
129
|
+
<%- opts = {:ok_button => 'Do it!', :cancel_button => 'Nope', :use_confirm => false} %>
|
124
130
|
<%- opts.delete(:ok_button) if params[:suppress_ok_button] %>
|
125
131
|
<%= best_in_place @user, :favorite_movie, opts %>
|
126
132
|
</td>
|
127
133
|
</tr>
|
128
134
|
</table>
|
129
|
-
<br
|
130
|
-
<hr
|
135
|
+
<br/>
|
136
|
+
<hr/>
|
131
137
|
<p>Try the <b>features of Best In Place</b>:</p>
|
132
138
|
<ul>
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
139
|
+
<li>Try giving wrong email values or too short address, inputs to see server errors.</li>
|
140
|
+
<li>Click on newsletter to change a boolean value</li>
|
141
|
+
<li>Click on country to change the value in a collection of values</li>
|
142
|
+
<li>Use the external handler to change the value of the name</li>
|
143
|
+
<li>Try making changes inside inputs or textareas and then press the ESC key to recover the old value</li>
|
138
144
|
</ul>
|
139
|
-
<p>More information on <a href="http://github.com/bernat/best_in_place">github</a> or
|
145
|
+
<p>More information on <a href="http://github.com/bernat/best_in_place">github</a> or
|
146
|
+
<a href="http://blog.bernatfarrero.com/in-place-editing-with-javascript-jquery-and-rails-3/">bernatfarrero.com</a>.
|
147
|
+
</p>
|
140
148
|
|
141
149
|
</div>
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table "cars", :force => true do |t|
|
3
|
+
t.string "model"
|
4
|
+
end
|
5
|
+
|
6
|
+
create_table "users", :force => true do |t|
|
7
|
+
t.string "name"
|
8
|
+
t.string "last_name"
|
9
|
+
t.string "address"
|
10
|
+
t.string "email", :null => false
|
11
|
+
t.string "zip"
|
12
|
+
t.string "country"
|
13
|
+
t.datetime "created_at", :null => false
|
14
|
+
t.datetime "updated_at", :null => false
|
15
|
+
t.boolean "receive_email"
|
16
|
+
t.text "description"
|
17
|
+
t.string "favorite_color"
|
18
|
+
t.text "favorite_books"
|
19
|
+
t.datetime "birth_date"
|
20
|
+
t.float "money"
|
21
|
+
t.float "money_proc"
|
22
|
+
t.string "height"
|
23
|
+
t.string "favorite_movie"
|
24
|
+
t.string "favorite_locale"
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
|
+
|
3
|
+
require 'combustion'
|
4
|
+
require 'capybara/rspec'
|
5
|
+
require 'best_in_place'
|
6
|
+
|
7
|
+
Combustion.initialize! :active_record, :action_controller,
|
8
|
+
:action_view, :sprockets
|
9
|
+
|
10
|
+
require 'rspec/rails'
|
11
|
+
require 'capybara/rails'
|
12
|
+
|
13
|
+
require 'best_in_place/test_helpers'
|
14
|
+
require_relative 'support/retry_on_timeout'
|
15
|
+
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.include BestInPlace::TestHelpers
|
19
|
+
config.use_transactional_fixtures = false
|
20
|
+
config.raise_errors_for_deprecations!
|
21
|
+
end
|
@@ -1,10 +1,7 @@
|
|
1
1
|
def retry_on_timeout(n = 3, &block)
|
2
2
|
block.call
|
3
|
-
rescue
|
4
|
-
if n
|
5
|
-
|
6
|
-
|
7
|
-
else
|
8
|
-
raise
|
9
|
-
end
|
3
|
+
rescue => e
|
4
|
+
fail if n.zero?
|
5
|
+
puts "Catched error: #{e.message}. #{n-1} more attempts."
|
6
|
+
retry_on_timeout(n - 1, &block)
|
10
7
|
end
|
data/spec/utils_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe BestInPlace::Utils do
|
4
|
+
include BestInPlace::Utils
|
5
|
+
describe '#build_best_in_place_id' do
|
6
|
+
it 'build id from symbol' do
|
7
|
+
expect(build_best_in_place_id(:user, :login)).to eq('best_in_place_user_login')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'build id from record' do
|
11
|
+
car = Cuca::Car.create
|
12
|
+
expect(build_best_in_place_id(car, :model)).to eq("best_in_place_cuca_car_#{car.id}_model")
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#object_to_key' do
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,272 @@
|
|
1
|
+
/*!
|
2
|
+
Autosize v1.18.9 - 2014-05-27
|
3
|
+
Automatically adjust textarea height based on user input.
|
4
|
+
(c) 2014 Jack Moore - http://www.jacklmoore.com/autosize
|
5
|
+
license: http://www.opensource.org/licenses/mit-license.php
|
6
|
+
*/
|
7
|
+
(function ($) {
|
8
|
+
'use strict';
|
9
|
+
var defaults = {
|
10
|
+
className: 'autosizejs',
|
11
|
+
id: 'autosizejs',
|
12
|
+
append: '\n',
|
13
|
+
callback: false,
|
14
|
+
resizeDelay: 10,
|
15
|
+
placeholder: true
|
16
|
+
},
|
17
|
+
|
18
|
+
// border:0 is unnecessary, but avoids a bug in Firefox on OSX
|
19
|
+
copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',
|
20
|
+
|
21
|
+
// line-height is conditionally included because IE7/IE8/old Opera do not return the correct value.
|
22
|
+
typographyStyles = [
|
23
|
+
'fontFamily',
|
24
|
+
'fontSize',
|
25
|
+
'fontWeight',
|
26
|
+
'fontStyle',
|
27
|
+
'letterSpacing',
|
28
|
+
'textTransform',
|
29
|
+
'wordSpacing',
|
30
|
+
'textIndent'
|
31
|
+
],
|
32
|
+
|
33
|
+
// to keep track which textarea is being mirrored when adjust() is called.
|
34
|
+
mirrored,
|
35
|
+
|
36
|
+
// the mirror element, which is used to calculate what size the mirrored element should be.
|
37
|
+
mirror = $(copy).data('autosize', true)[0];
|
38
|
+
|
39
|
+
// test that line-height can be accurately copied.
|
40
|
+
mirror.style.lineHeight = '99px';
|
41
|
+
if ($(mirror).css('lineHeight') === '99px') {
|
42
|
+
typographyStyles.push('lineHeight');
|
43
|
+
}
|
44
|
+
mirror.style.lineHeight = '';
|
45
|
+
|
46
|
+
$.fn.autosize = function (options) {
|
47
|
+
if (!this.length) {
|
48
|
+
return this;
|
49
|
+
}
|
50
|
+
|
51
|
+
options = $.extend({}, defaults, options || {});
|
52
|
+
|
53
|
+
if (mirror.parentNode !== document.body) {
|
54
|
+
$(document.body).append(mirror);
|
55
|
+
}
|
56
|
+
|
57
|
+
return this.each(function () {
|
58
|
+
var
|
59
|
+
ta = this,
|
60
|
+
$ta = $(ta),
|
61
|
+
maxHeight,
|
62
|
+
minHeight,
|
63
|
+
boxOffset = 0,
|
64
|
+
callback = $.isFunction(options.callback),
|
65
|
+
originalStyles = {
|
66
|
+
height: ta.style.height,
|
67
|
+
overflow: ta.style.overflow,
|
68
|
+
overflowY: ta.style.overflowY,
|
69
|
+
wordWrap: ta.style.wordWrap,
|
70
|
+
resize: ta.style.resize
|
71
|
+
},
|
72
|
+
timeout,
|
73
|
+
width = $ta.width(),
|
74
|
+
taResize = $ta.css('resize');
|
75
|
+
|
76
|
+
if ($ta.data('autosize')) {
|
77
|
+
// exit if autosize has already been applied, or if the textarea is the mirror element.
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
$ta.data('autosize', true);
|
81
|
+
|
82
|
+
if ($ta.css('box-sizing') === 'border-box' || $ta.css('-moz-box-sizing') === 'border-box' || $ta.css('-webkit-box-sizing') === 'border-box'){
|
83
|
+
boxOffset = $ta.outerHeight() - $ta.height();
|
84
|
+
}
|
85
|
+
|
86
|
+
// IE8 and lower return 'auto', which parses to NaN, if no min-height is set.
|
87
|
+
minHeight = Math.max(parseInt($ta.css('minHeight'), 10) - boxOffset || 0, $ta.height());
|
88
|
+
|
89
|
+
$ta.css({
|
90
|
+
overflow: 'hidden',
|
91
|
+
overflowY: 'hidden',
|
92
|
+
wordWrap: 'break-word' // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width
|
93
|
+
});
|
94
|
+
|
95
|
+
if (taResize === 'vertical') {
|
96
|
+
$ta.css('resize','none');
|
97
|
+
} else if (taResize === 'both') {
|
98
|
+
$ta.css('resize', 'horizontal');
|
99
|
+
}
|
100
|
+
|
101
|
+
// The mirror width must exactly match the textarea width, so using getBoundingClientRect because it doesn't round the sub-pixel value.
|
102
|
+
// window.getComputedStyle, getBoundingClientRect returning a width are unsupported, but also unneeded in IE8 and lower.
|
103
|
+
function setWidth() {
|
104
|
+
var width;
|
105
|
+
var style = window.getComputedStyle ? window.getComputedStyle(ta, null) : false;
|
106
|
+
|
107
|
+
if (style) {
|
108
|
+
|
109
|
+
width = ta.getBoundingClientRect().width;
|
110
|
+
|
111
|
+
if (width === 0 || typeof width !== 'number') {
|
112
|
+
width = parseInt(style.width,10);
|
113
|
+
}
|
114
|
+
|
115
|
+
$.each(['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'], function(i,val){
|
116
|
+
width -= parseInt(style[val],10);
|
117
|
+
});
|
118
|
+
} else {
|
119
|
+
width = $ta.width();
|
120
|
+
}
|
121
|
+
|
122
|
+
mirror.style.width = Math.max(width,0) + 'px';
|
123
|
+
}
|
124
|
+
|
125
|
+
function initMirror() {
|
126
|
+
var styles = {};
|
127
|
+
|
128
|
+
mirrored = ta;
|
129
|
+
mirror.className = options.className;
|
130
|
+
mirror.id = options.id;
|
131
|
+
maxHeight = parseInt($ta.css('maxHeight'), 10);
|
132
|
+
|
133
|
+
// mirror is a duplicate textarea located off-screen that
|
134
|
+
// is automatically updated to contain the same text as the
|
135
|
+
// original textarea. mirror always has a height of 0.
|
136
|
+
// This gives a cross-browser supported way getting the actual
|
137
|
+
// height of the text, through the scrollTop property.
|
138
|
+
$.each(typographyStyles, function(i,val){
|
139
|
+
styles[val] = $ta.css(val);
|
140
|
+
});
|
141
|
+
|
142
|
+
$(mirror).css(styles).attr('wrap', $ta.attr('wrap'));
|
143
|
+
|
144
|
+
setWidth();
|
145
|
+
|
146
|
+
// Chrome-specific fix:
|
147
|
+
// When the textarea y-overflow is hidden, Chrome doesn't reflow the text to account for the space
|
148
|
+
// made available by removing the scrollbar. This workaround triggers the reflow for Chrome.
|
149
|
+
if (window.chrome) {
|
150
|
+
var width = ta.style.width;
|
151
|
+
ta.style.width = '0px';
|
152
|
+
var ignore = ta.offsetWidth;
|
153
|
+
ta.style.width = width;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
// Using mainly bare JS in this function because it is going
|
158
|
+
// to fire very often while typing, and needs to very efficient.
|
159
|
+
function adjust() {
|
160
|
+
var height, original;
|
161
|
+
|
162
|
+
if (mirrored !== ta) {
|
163
|
+
initMirror();
|
164
|
+
} else {
|
165
|
+
setWidth();
|
166
|
+
}
|
167
|
+
|
168
|
+
if (!ta.value && options.placeholder) {
|
169
|
+
// If the textarea is empty, copy the placeholder text into
|
170
|
+
// the mirror control and use that for sizing so that we
|
171
|
+
// don't end up with placeholder getting trimmed.
|
172
|
+
mirror.value = ($ta.attr("placeholder") || '') + options.append;
|
173
|
+
} else {
|
174
|
+
mirror.value = ta.value + options.append;
|
175
|
+
}
|
176
|
+
|
177
|
+
mirror.style.overflowY = ta.style.overflowY;
|
178
|
+
original = parseInt(ta.style.height,10);
|
179
|
+
|
180
|
+
// Setting scrollTop to zero is needed in IE8 and lower for the next step to be accurately applied
|
181
|
+
mirror.scrollTop = 0;
|
182
|
+
|
183
|
+
mirror.scrollTop = 9e4;
|
184
|
+
|
185
|
+
// Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding.
|
186
|
+
height = mirror.scrollTop;
|
187
|
+
|
188
|
+
if (maxHeight && height > maxHeight) {
|
189
|
+
ta.style.overflowY = 'scroll';
|
190
|
+
height = maxHeight;
|
191
|
+
} else {
|
192
|
+
ta.style.overflowY = 'hidden';
|
193
|
+
if (height < minHeight) {
|
194
|
+
height = minHeight;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
height += boxOffset;
|
199
|
+
|
200
|
+
if (original !== height) {
|
201
|
+
ta.style.height = height + 'px';
|
202
|
+
if (callback) {
|
203
|
+
options.callback.call(ta,ta);
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
function resize () {
|
209
|
+
clearTimeout(timeout);
|
210
|
+
timeout = setTimeout(function(){
|
211
|
+
var newWidth = $ta.width();
|
212
|
+
|
213
|
+
if (newWidth !== width) {
|
214
|
+
width = newWidth;
|
215
|
+
adjust();
|
216
|
+
}
|
217
|
+
}, parseInt(options.resizeDelay,10));
|
218
|
+
}
|
219
|
+
|
220
|
+
if ('onpropertychange' in ta) {
|
221
|
+
if ('oninput' in ta) {
|
222
|
+
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
223
|
+
// so binding to onkeyup to catch most of those occasions. There is no way that I
|
224
|
+
// know of to detect something like 'cut' in IE9.
|
225
|
+
$ta.on('input.autosize keyup.autosize', adjust);
|
226
|
+
} else {
|
227
|
+
// IE7 / IE8
|
228
|
+
$ta.on('propertychange.autosize', function(){
|
229
|
+
if(event.propertyName === 'value'){
|
230
|
+
adjust();
|
231
|
+
}
|
232
|
+
});
|
233
|
+
}
|
234
|
+
} else {
|
235
|
+
// Modern Browsers
|
236
|
+
$ta.on('input.autosize', adjust);
|
237
|
+
}
|
238
|
+
|
239
|
+
// Set options.resizeDelay to false if using fixed-width textarea elements.
|
240
|
+
// Uses a timeout and width check to reduce the amount of times adjust needs to be called after window resize.
|
241
|
+
|
242
|
+
if (options.resizeDelay !== false) {
|
243
|
+
$(window).on('resize.autosize', resize);
|
244
|
+
}
|
245
|
+
|
246
|
+
// Event for manual triggering if needed.
|
247
|
+
// Should only be needed when the value of the textarea is changed through JavaScript rather than user input.
|
248
|
+
$ta.on('autosize.resize', adjust);
|
249
|
+
|
250
|
+
// Event for manual triggering that also forces the styles to update as well.
|
251
|
+
// Should only be needed if one of typography styles of the textarea change, and the textarea is already the target of the adjust method.
|
252
|
+
$ta.on('autosize.resizeIncludeStyle', function() {
|
253
|
+
mirrored = null;
|
254
|
+
adjust();
|
255
|
+
});
|
256
|
+
|
257
|
+
$ta.on('autosize.destroy', function(){
|
258
|
+
mirrored = null;
|
259
|
+
clearTimeout(timeout);
|
260
|
+
$(window).off('resize', resize);
|
261
|
+
$ta
|
262
|
+
.off('autosize')
|
263
|
+
.off('.autosize')
|
264
|
+
.css(originalStyles)
|
265
|
+
.removeData('autosize');
|
266
|
+
});
|
267
|
+
|
268
|
+
// Call adjust in case the textarea already contains text.
|
269
|
+
adjust();
|
270
|
+
});
|
271
|
+
};
|
272
|
+
}(window.jQuery || window.$)); // jQuery or jQuery-like library, such as Zepto
|