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
data/best_in_place.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require
|
3
|
+
require 'best_in_place/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "best_in_place"
|
@@ -9,20 +9,22 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Bernat Farrero"]
|
10
10
|
s.email = ["bernat@itnig.net"]
|
11
11
|
s.homepage = "http://github.com/bernat/best_in_place"
|
12
|
-
s.summary =
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
s.summary = <<SUM
|
13
|
+
It makes any field in place editable by clicking on it, it works for inputs,
|
14
|
+
textareas, select dropdowns and checkboxes
|
15
|
+
SUM
|
16
|
+
s.description = <<DESC
|
17
|
+
BestInPlace is a jQuery script and a Rails helper that provide the method best_in_place to display
|
18
|
+
any object field easily editable for the user by just clicking on it. It supports input data,
|
19
|
+
text data, boolean data and custom dropdown data. It works with RESTful controllers.
|
20
|
+
DESC
|
16
21
|
|
17
22
|
s.files = `git ls-files`.split("\n")
|
18
|
-
s.test_files = `git ls-files -- {
|
23
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
19
24
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
25
|
s.require_paths = ["lib"]
|
21
26
|
|
22
|
-
s.
|
23
|
-
s.
|
27
|
+
s.add_runtime_dependency 'actionpack', '>= 3.2'
|
28
|
+
s.add_runtime_dependency 'railties', '>= 3.2'
|
24
29
|
|
25
|
-
s.add_development_dependency "rspec-rails", "~> 2.8.0"
|
26
|
-
s.add_development_dependency "nokogiri"
|
27
|
-
s.add_development_dependency "capybara", "~> 1.1.2"
|
28
30
|
end
|
data/config.ru
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
source "https://rails-assets.org"
|
5
|
+
|
6
|
+
gem "rails-assets-jquery", "1.11.1"
|
7
|
+
gem "rails-assets-jquery-ui", "1.10.4"
|
8
|
+
gem "rdiscount"
|
9
|
+
gem "rspec-rails"
|
10
|
+
gem "nokogiri"
|
11
|
+
gem "combustion"
|
12
|
+
gem "sprockets-rails"
|
13
|
+
gem "capybara"
|
14
|
+
gem "selenium-webdriver"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "appraisal"
|
17
|
+
gem "rails", "3.2.19"
|
18
|
+
gem "strong_parameters"
|
19
|
+
|
20
|
+
platforms :mri_21 do
|
21
|
+
gem "byebug"
|
22
|
+
end
|
23
|
+
|
24
|
+
gemspec :path => "../"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
source "https://rails-assets.org"
|
5
|
+
|
6
|
+
gem "rails-assets-jquery", "1.11.1"
|
7
|
+
gem "rails-assets-jquery-ui", "1.10.4"
|
8
|
+
gem "rdiscount"
|
9
|
+
gem "rspec-rails"
|
10
|
+
gem "nokogiri"
|
11
|
+
gem "combustion"
|
12
|
+
gem "sprockets-rails"
|
13
|
+
gem "capybara"
|
14
|
+
gem "selenium-webdriver"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "appraisal"
|
17
|
+
gem "rails", "~> 4.0.0"
|
18
|
+
|
19
|
+
platforms :mri_21 do
|
20
|
+
gem "byebug"
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec :path => "../"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
source "https://rails-assets.org"
|
5
|
+
|
6
|
+
gem "rails-assets-jquery", "1.11.1"
|
7
|
+
gem "rails-assets-jquery-ui", "1.10.4"
|
8
|
+
gem "rdiscount"
|
9
|
+
gem "rspec-rails"
|
10
|
+
gem "nokogiri"
|
11
|
+
gem "combustion"
|
12
|
+
gem "sprockets-rails"
|
13
|
+
gem "capybara"
|
14
|
+
gem "selenium-webdriver"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "appraisal"
|
17
|
+
gem "rails", "~> 4.1.0"
|
18
|
+
|
19
|
+
platforms :mri_21 do
|
20
|
+
gem "byebug"
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec :path => "../"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
source "https://rails-assets.org"
|
5
|
+
|
6
|
+
gem "rails-assets-jquery", "1.11.1"
|
7
|
+
gem "rails-assets-jquery-ui", "1.10.4"
|
8
|
+
gem "rdiscount"
|
9
|
+
gem "rspec-rails"
|
10
|
+
gem "nokogiri"
|
11
|
+
gem "combustion"
|
12
|
+
gem "sprockets-rails"
|
13
|
+
gem "capybara"
|
14
|
+
gem "selenium-webdriver"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "appraisal"
|
17
|
+
gem "rails", :github => "rails/rails"
|
18
|
+
gem "arel", :github => "rails/arel"
|
19
|
+
gem "minitest"
|
20
|
+
|
21
|
+
platforms :mri_21 do
|
22
|
+
gem "byebug"
|
23
|
+
end
|
24
|
+
|
25
|
+
gemspec :path => "../"
|
@@ -0,0 +1,57 @@
|
|
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
|
+
if (this.inner_class !== null) {
|
22
|
+
input_elt.addClass(this.inner_class);
|
23
|
+
}
|
24
|
+
output.append(input_elt);
|
25
|
+
|
26
|
+
this.element.html(output);
|
27
|
+
this.setHtmlAttributes();
|
28
|
+
this.element.find('input')[0].select();
|
29
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
30
|
+
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
31
|
+
|
32
|
+
this.element.find('input')
|
33
|
+
.datepicker({
|
34
|
+
onClose: function () {
|
35
|
+
that.update();
|
36
|
+
}
|
37
|
+
})
|
38
|
+
.datepicker('show');
|
39
|
+
},
|
40
|
+
|
41
|
+
getValue: function () {
|
42
|
+
'use strict';
|
43
|
+
return this.sanitizeValue(this.element.find("input").val());
|
44
|
+
},
|
45
|
+
|
46
|
+
submitHandler: function (event) {
|
47
|
+
'use strict';
|
48
|
+
event.data.editor.update();
|
49
|
+
},
|
50
|
+
|
51
|
+
keyupHandler: function (event) {
|
52
|
+
'use strict';
|
53
|
+
if (event.keyCode === 27) {
|
54
|
+
event.data.editor.abort();
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
@@ -1,740 +1,641 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
21
23
|
|
22
24
|
function BestInPlaceEditor(e) {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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);
|
28
31
|
}
|
29
32
|
|
30
33
|
BestInPlaceEditor.prototype = {
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
61
|
-
},
|
62
|
-
|
63
|
-
abortIfConfirm : function () {
|
64
|
-
if (!this.useConfirm) {
|
65
|
-
this.abort();
|
66
|
-
return;
|
67
|
-
}
|
68
|
-
|
69
|
-
if (confirm("Are you sure you want to discard your changes?")) {
|
70
|
-
this.abort();
|
71
|
-
}
|
72
|
-
},
|
73
|
-
|
74
|
-
update : function() {
|
75
|
-
var editor = this;
|
76
|
-
if (this.formType in {"input":1, "textarea":1} && this.getValue() == this.oldValue)
|
77
|
-
{ // Avoid request if no change is made
|
78
|
-
this.abort();
|
79
|
-
return true;
|
80
|
-
}
|
81
|
-
editor.ajax({
|
82
|
-
"type" : "post",
|
83
|
-
"dataType" : "text",
|
84
|
-
"data" : editor.requestData(),
|
85
|
-
"success" : function(data){ editor.loadSuccessCallback(data); },
|
86
|
-
"error" : function(request, error){ editor.loadErrorCallback(request, error); }
|
87
|
-
});
|
88
|
-
if (this.formType == "select") {
|
89
|
-
var value = this.getValue();
|
90
|
-
this.previousCollectionValue = value;
|
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();
|
91
63
|
|
92
|
-
|
93
|
-
if (value == v[0]) {
|
94
|
-
editor.element.html(v[1]);
|
64
|
+
}
|
95
65
|
}
|
96
|
-
}
|
97
|
-
);
|
98
|
-
} else if (this.formType == "checkbox") {
|
99
|
-
editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
|
100
|
-
} else {
|
101
|
-
if (this.getValue() !== "") {
|
102
|
-
editor.element.text(this.getValue());
|
103
|
-
} else {
|
104
|
-
editor.element.html(this.nil);
|
105
|
-
}
|
106
|
-
}
|
107
|
-
editor.element.trigger(jQuery.Event("best_in_place:update"));
|
108
|
-
},
|
109
|
-
|
110
|
-
activateForm : function() {
|
111
|
-
alert("The form was not properly initialized. activateForm is unbound");
|
112
|
-
},
|
113
|
-
|
114
|
-
activateText : function(value){
|
115
|
-
this.element.html(value);
|
116
|
-
if(this.isNil()) this.element.html(this.nil);
|
117
|
-
},
|
118
|
-
|
119
|
-
// Helper Functions ////////////////////////////////////////////////////////
|
120
|
-
|
121
|
-
initOptions : function() {
|
122
|
-
// Try parent supplied info
|
123
|
-
var self = this;
|
124
|
-
self.element.parents().each(function(){
|
125
|
-
$parent = jQuery(this);
|
126
|
-
self.url = self.url || $parent.attr("data-url");
|
127
|
-
self.collection = self.collection || $parent.attr("data-collection");
|
128
|
-
self.formType = self.formType || $parent.attr("data-type");
|
129
|
-
self.objectName = self.objectName || $parent.attr("data-object");
|
130
|
-
self.attributeName = self.attributeName || $parent.attr("data-attribute");
|
131
|
-
self.activator = self.activator || $parent.attr("data-activator");
|
132
|
-
self.okButton = self.okButton || $parent.attr("data-ok-button");
|
133
|
-
self.okButtonClass = self.okButtonClass || $parent.attr("data-ok-button-class");
|
134
|
-
self.cancelButton = self.cancelButton || $parent.attr("data-cancel-button");
|
135
|
-
self.cancelButtonClass = self.cancelButtonClass || $parent.attr("data-cancel-button-class");
|
136
|
-
self.nil = self.nil || $parent.attr("data-nil");
|
137
|
-
self.inner_class = self.inner_class || $parent.attr("data-inner-class");
|
138
|
-
self.html_attrs = self.html_attrs || $parent.attr("data-html-attrs");
|
139
|
-
self.original_content = self.original_content || $parent.attr("data-original-content");
|
140
|
-
self.collectionValue = self.collectionValue || $parent.attr("data-value");
|
141
|
-
});
|
142
|
-
|
143
|
-
// Try Rails-id based if parents did not explicitly supply something
|
144
|
-
self.element.parents().each(function(){
|
145
|
-
var res = this.id.match(/^(\w+)_(\d+)$/i);
|
146
|
-
if (res) {
|
147
|
-
self.objectName = self.objectName || res[1];
|
148
|
-
}
|
149
|
-
});
|
150
66
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
self.activator = self.element.attr("data-activator") || self.element;
|
158
|
-
self.okButton = self.element.attr("data-ok-button") || self.okButton;
|
159
|
-
self.okButtonClass = self.element.attr("data-ok-button-class") || self.okButtonClass || "";
|
160
|
-
self.cancelButton = self.element.attr("data-cancel-button") || self.cancelButton;
|
161
|
-
self.cancelButtonClass = self.element.attr("data-cancel-button-class") || self.cancelButtonClass || "";
|
162
|
-
self.nil = self.element.attr("data-nil") || self.nil || "—";
|
163
|
-
self.inner_class = self.element.attr("data-inner-class") || self.inner_class || null;
|
164
|
-
self.html_attrs = self.element.attr("data-html-attrs") || self.html_attrs;
|
165
|
-
self.original_content = self.element.attr("data-original-content") || self.original_content;
|
166
|
-
self.collectionValue = self.element.attr("data-value") || self.collectionValue;
|
167
|
-
|
168
|
-
if (!self.element.attr("data-sanitize")) {
|
169
|
-
self.sanitize = true;
|
170
|
-
}
|
171
|
-
else {
|
172
|
-
self.sanitize = (self.element.attr("data-sanitize") == "true");
|
173
|
-
}
|
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
|
+
},
|
174
73
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
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
|
+
},
|
180
81
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
82
|
+
abortIfConfirm: function () {
|
83
|
+
'use strict';
|
84
|
+
if (!this.useConfirm) {
|
85
|
+
this.abort();
|
86
|
+
return;
|
87
|
+
}
|
185
88
|
|
186
|
-
|
89
|
+
if (confirm(BestInPlaceEditor.defaults.locales[''].confirmMessage)) {
|
90
|
+
this.abort();
|
91
|
+
}
|
92
|
+
},
|
187
93
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
94
|
+
update: function () {
|
95
|
+
'use strict';
|
96
|
+
var editor = this,
|
97
|
+
value = this.getValue();
|
192
98
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
},
|
199
|
-
|
200
|
-
isNil: function() {
|
201
|
-
// TODO: It only work when form is deactivated.
|
202
|
-
// Condition will fail when form is activated
|
203
|
-
return this.element.html() === "" || this.element.html() === this.nil;
|
204
|
-
},
|
205
|
-
|
206
|
-
getValue : function() {
|
207
|
-
alert("The form was not properly initialized. getValue is unbound");
|
208
|
-
},
|
209
|
-
|
210
|
-
// Trim and Strips HTML from text
|
211
|
-
sanitizeValue : function(s) {
|
212
|
-
return jQuery.trim(s);
|
213
|
-
},
|
214
|
-
|
215
|
-
/* Generate the data sent in the POST request */
|
216
|
-
requestData : function() {
|
217
|
-
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
218
|
-
csrf_token = jQuery('meta[name=csrf-token]').attr('content');
|
219
|
-
csrf_param = jQuery('meta[name=csrf-param]').attr('content');
|
220
|
-
|
221
|
-
var data = "_method=put";
|
222
|
-
data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
|
223
|
-
|
224
|
-
if (csrf_param !== undefined && csrf_token !== undefined) {
|
225
|
-
data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
|
226
|
-
}
|
227
|
-
return data;
|
228
|
-
},
|
229
|
-
|
230
|
-
ajax : function(options) {
|
231
|
-
options.url = this.url;
|
232
|
-
options.beforeSend = function(xhr){ xhr.setRequestHeader("Accept", "application/json"); };
|
233
|
-
return jQuery.ajax(options);
|
234
|
-
},
|
235
|
-
|
236
|
-
// Handlers ////////////////////////////////////////////////////////////////
|
237
|
-
|
238
|
-
loadSuccessCallback : function(data) {
|
239
|
-
data = jQuery.trim(data);
|
240
|
-
|
241
|
-
if(data && data!=""){
|
242
|
-
var response = jQuery.parseJSON(jQuery.trim(data));
|
243
|
-
if (response !== null && response.hasOwnProperty("display_as")) {
|
244
|
-
this.element.attr("data-original-content", this.element.text());
|
245
|
-
this.original_content = this.element.text();
|
246
|
-
this.element.html(response["display_as"]);
|
247
|
-
}
|
248
|
-
|
249
|
-
this.element.trigger(jQuery.Event("best_in_place:success"), data);
|
250
|
-
this.element.trigger(jQuery.Event("ajax:success"), data);
|
251
|
-
} else {
|
252
|
-
this.element.trigger(jQuery.Event("best_in_place:success"));
|
253
|
-
this.element.trigger(jQuery.Event("ajax:success"));
|
254
|
-
}
|
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
|
+
}
|
255
104
|
|
256
|
-
|
257
|
-
|
258
|
-
|
105
|
+
editor.ajax({
|
106
|
+
"type": BestInPlaceEditor.defaults.ajaxMethod,
|
107
|
+
"dataType": BestInPlaceEditor.defaults.ajaxDataType,
|
108
|
+
"data": editor.requestData(),
|
109
|
+
"success": function (data) {
|
110
|
+
editor.loadSuccessCallback(data);
|
111
|
+
},
|
112
|
+
"error": function (request, error) {
|
113
|
+
editor.loadErrorCallback(request, error);
|
114
|
+
}
|
115
|
+
});
|
259
116
|
|
260
|
-
if (this.collectionValue !== null && this.formType == "select") {
|
261
|
-
this.collectionValue = this.previousCollectionValue;
|
262
|
-
this.previousCollectionValue = null;
|
263
|
-
}
|
264
|
-
},
|
265
117
|
|
266
|
-
|
267
|
-
|
118
|
+
switch (this.formType) {
|
119
|
+
case "select":
|
120
|
+
this.previousCollectionValue = value;
|
121
|
+
|
122
|
+
// search for the text for the span
|
123
|
+
jQuery.each(this.values, function (i, v) {
|
124
|
+
if (String(value) === String(i)) {
|
125
|
+
editor.element.html(v);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
);
|
129
|
+
break;
|
130
|
+
|
131
|
+
case "checkbox":
|
132
|
+
editor.element.html(this.values[value]);
|
133
|
+
break;
|
134
|
+
|
135
|
+
default:
|
136
|
+
if (value !== "") {
|
137
|
+
if (this.display_raw) {
|
138
|
+
editor.element.html(value);
|
139
|
+
} else {
|
140
|
+
editor.element.text(value);
|
141
|
+
}
|
142
|
+
} else {
|
143
|
+
editor.element.html(this.placeHolder);
|
144
|
+
}
|
145
|
+
}
|
268
146
|
|
269
|
-
|
270
|
-
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
147
|
+
editor.element.data('bipValue', value);
|
271
148
|
|
272
|
-
|
273
|
-
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
274
|
-
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
275
|
-
},
|
276
|
-
|
277
|
-
clickHandler : function(event) {
|
278
|
-
event.preventDefault();
|
279
|
-
event.data.editor.activate();
|
280
|
-
},
|
281
|
-
|
282
|
-
setHtmlAttributes : function() {
|
283
|
-
var formField = this.element.find(this.formType);
|
284
|
-
|
285
|
-
if(this.html_attrs){
|
286
|
-
var attrs = jQuery.parseJSON(this.html_attrs);
|
287
|
-
for(var key in attrs){
|
288
|
-
formField.attr(key, attrs[key]);
|
289
|
-
}
|
290
|
-
}
|
291
|
-
}
|
292
|
-
};
|
149
|
+
editor.element.trigger(jQuery.Event("best_in_place:update"));
|
293
150
|
|
294
151
|
|
295
|
-
// Button cases:
|
296
|
-
// If no buttons, then blur saves, ESC cancels
|
297
|
-
// If just Cancel button, then blur saves, ESC or clicking Cancel cancels (careful of blur event!)
|
298
|
-
// If just OK button, then clicking OK saves (careful of blur event!), ESC or blur cancels
|
299
|
-
// If both buttons, then clicking OK saves, ESC or clicking Cancel or blur cancels
|
300
|
-
BestInPlaceEditor.forms = {
|
301
|
-
"input" : {
|
302
|
-
activateForm : function() {
|
303
|
-
var output = jQuery(document.createElement('form'))
|
304
|
-
.addClass('form_in_place')
|
305
|
-
.attr('action', 'javascript:void(0);')
|
306
|
-
.attr('style', 'display:inline');
|
307
|
-
var input_elt = jQuery(document.createElement('input'))
|
308
|
-
.attr('type', 'text')
|
309
|
-
.attr('name', this.attributeName)
|
310
|
-
.val(this.display_value);
|
311
|
-
if(this.inner_class !== null) {
|
312
|
-
input_elt.addClass(this.inner_class);
|
313
|
-
}
|
314
|
-
output.append(input_elt);
|
315
|
-
if(this.okButton) {
|
316
|
-
output.append(
|
317
|
-
jQuery(document.createElement('input'))
|
318
|
-
.attr('type', 'submit')
|
319
|
-
.attr('class', this.okButtonClass)
|
320
|
-
.attr('value', this.okButton)
|
321
|
-
)
|
322
|
-
}
|
323
|
-
if(this.cancelButton) {
|
324
|
-
output.append(
|
325
|
-
jQuery(document.createElement('input'))
|
326
|
-
.attr('type', 'button')
|
327
|
-
.attr('class', this.cancelButtonClass)
|
328
|
-
.attr('value', this.cancelButton)
|
329
|
-
)
|
330
|
-
}
|
331
|
-
|
332
|
-
this.element.html(output);
|
333
|
-
this.setHtmlAttributes();
|
334
|
-
this.element.find("input[type='text']")[0].select();
|
335
|
-
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
336
|
-
if (this.cancelButton) {
|
337
|
-
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
|
338
|
-
}
|
339
|
-
this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
340
|
-
this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
341
|
-
this.blurTimer = null;
|
342
|
-
this.userClicked = false;
|
343
152
|
},
|
344
153
|
|
345
|
-
|
346
|
-
|
154
|
+
activateForm: function () {
|
155
|
+
'use strict';
|
156
|
+
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
347
157
|
},
|
348
158
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
event.data.editor.abort();
|
355
|
-
}
|
356
|
-
}, 500);
|
357
|
-
} else {
|
358
|
-
if (event.data.editor.cancelButton) {
|
359
|
-
event.data.editor.blurTimer = setTimeout(function () {
|
360
|
-
if (!event.data.editor.userClicked) {
|
361
|
-
event.data.editor.update();
|
362
|
-
}
|
363
|
-
}, 500);
|
364
|
-
} else {
|
365
|
-
event.data.editor.update();
|
159
|
+
activateText: function (value) {
|
160
|
+
'use strict';
|
161
|
+
this.element.html(value);
|
162
|
+
if (this.isPlaceHolder()) {
|
163
|
+
this.element.html(this.placeHolder);
|
366
164
|
}
|
367
|
-
}
|
368
165
|
},
|
369
166
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
167
|
+
// Helper Functions ////////////////////////////////////////////////////////
|
168
|
+
|
169
|
+
initOptions: function () {
|
170
|
+
// Try parent supplied info
|
171
|
+
'use strict';
|
172
|
+
var self = this;
|
173
|
+
self.element.parents().each(function () {
|
174
|
+
var $parent = jQuery(this);
|
175
|
+
self.url = self.url || $parent.data("bipUrl");
|
176
|
+
self.activator = self.activator || $parent.data("bipActivator");
|
177
|
+
self.okButton = self.okButton || $parent.data("bipOkButton");
|
178
|
+
self.okButtonClass = self.okButtonClass || $parent.data("bipOkButtonClass");
|
179
|
+
self.cancelButton = self.cancelButton || $parent.data("bipCancelButton");
|
180
|
+
self.cancelButtonClass = self.cancelButtonClass || $parent.data("bipCancelButtonClass");
|
181
|
+
});
|
375
182
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
183
|
+
// Load own attributes (overrides all others)
|
184
|
+
self.url = self.element.data("bipUrl") || self.url || document.location.pathname;
|
185
|
+
self.collection = self.element.data("bipCollection") || self.collection;
|
186
|
+
self.formType = self.element.data("bipType") || "input";
|
187
|
+
self.objectName = self.element.data("bipObject") || self.objectName;
|
188
|
+
self.attributeName = self.element.data("bipAttribute") || self.attributeName;
|
189
|
+
self.activator = self.element.data("bipActivator") || self.element;
|
190
|
+
self.okButton = self.element.data("bipOkButton") || self.okButton;
|
191
|
+
self.okButtonClass = self.element.data("bipOkButtonClass") || self.okButtonClass || BestInPlaceEditor.defaults.okButtonClass;
|
192
|
+
self.cancelButton = self.element.data("bipCancelButton") || self.cancelButton;
|
193
|
+
self.cancelButtonClass = self.element.data("bipCancelButtonClass") || self.cancelButtonClass || BestInPlaceEditor.defaults.cancelButtonClass;
|
194
|
+
self.placeHolder = self.element.data("bipPlaceholder") || BestInPlaceEditor.defaults.locales[''].placeHolder;
|
195
|
+
self.inner_class = self.element.data("bipInnerClass");
|
196
|
+
self.html_attrs = self.element.data("bipHtmlAttrs");
|
197
|
+
self.original_content = self.element.data("bipOriginalContent") || self.original_content;
|
198
|
+
|
199
|
+
// if set the input won't be satinized
|
200
|
+
self.display_raw = self.element.data("bip-raw");
|
201
|
+
|
202
|
+
self.useConfirm = self.element.data("bip-confirm");
|
203
|
+
|
204
|
+
|
205
|
+
if (self.formType === "select" || self.formType === "checkbox") {
|
206
|
+
self.values = self.collection;
|
207
|
+
self.collectionValue = self.element.data("bipValue") || self.collectionValue;
|
208
|
+
}
|
381
209
|
},
|
382
210
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
}
|
388
|
-
},
|
389
|
-
|
390
|
-
"date" : {
|
391
|
-
activateForm : function() {
|
392
|
-
var that = this,
|
393
|
-
output = jQuery(document.createElement('form'))
|
394
|
-
.addClass('form_in_place')
|
395
|
-
.attr('action', 'javascript:void(0);')
|
396
|
-
.attr('style', 'display:inline'),
|
397
|
-
input_elt = jQuery(document.createElement('input'))
|
398
|
-
.attr('type', 'text')
|
399
|
-
.attr('name', this.attributeName)
|
400
|
-
.attr('value', this.sanitizeValue(this.display_value));
|
401
|
-
if(this.inner_class !== null) {
|
402
|
-
input_elt.addClass(this.inner_class);
|
403
|
-
}
|
404
|
-
output.append(input_elt)
|
405
|
-
|
406
|
-
this.element.html(output);
|
407
|
-
this.setHtmlAttributes();
|
408
|
-
this.element.find('input')[0].select();
|
409
|
-
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
410
|
-
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
411
|
-
|
412
|
-
this.element.find('input')
|
413
|
-
.datepicker({
|
414
|
-
onClose: function() {
|
415
|
-
that.update();
|
416
|
-
}
|
417
|
-
})
|
418
|
-
.datepicker('show');
|
211
|
+
bindForm: function () {
|
212
|
+
'use strict';
|
213
|
+
this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
|
214
|
+
this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
|
419
215
|
},
|
420
216
|
|
421
|
-
getValue : function() {
|
422
|
-
return this.sanitizeValue(this.element.find("input").val());
|
423
|
-
},
|
424
217
|
|
425
|
-
|
426
|
-
|
218
|
+
initPlaceHolder: function () {
|
219
|
+
'use strict';
|
220
|
+
// TODO add placeholder for select and checkbox
|
221
|
+
if (this.element.html() === "") {
|
222
|
+
this.element.html(this.placeHolder);
|
223
|
+
}
|
427
224
|
},
|
428
225
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
},
|
435
|
-
|
436
|
-
"select" : {
|
437
|
-
activateForm : function() {
|
438
|
-
var output = jQuery(document.createElement('form'))
|
439
|
-
.attr('action', 'javascript:void(0)')
|
440
|
-
.attr('style', 'display:inline');
|
441
|
-
selected = '',
|
442
|
-
oldValue = this.oldValue,
|
443
|
-
select_elt = jQuery(document.createElement('select'))
|
444
|
-
.attr('class', this.inned_class !== null ? this.inner_class : '' ),
|
445
|
-
currentCollectionValue = this.collectionValue;
|
446
|
-
|
447
|
-
jQuery.each(this.values, function (index, value) {
|
448
|
-
var option_elt = jQuery(document.createElement('option'))
|
449
|
-
// .attr('value', value[0])
|
450
|
-
.val(value[0])
|
451
|
-
.html(value[1]);
|
452
|
-
if(value[0] == currentCollectionValue) {
|
453
|
-
option_elt.attr('selected', 'selected');
|
454
|
-
}
|
455
|
-
select_elt.append(option_elt);
|
456
|
-
});
|
457
|
-
output.append(select_elt);
|
458
|
-
|
459
|
-
this.element.html(output);
|
460
|
-
this.setHtmlAttributes();
|
461
|
-
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
462
|
-
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
463
|
-
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
464
|
-
this.element.find("select")[0].focus();
|
226
|
+
isPlaceHolder: function () {
|
227
|
+
'use strict';
|
228
|
+
// TODO: It only work when form is deactivated.
|
229
|
+
// Condition will fail when form is activated
|
230
|
+
return this.element.html() === "" || this.element.html() === this.placeHolder;
|
465
231
|
},
|
466
232
|
|
467
|
-
getValue
|
468
|
-
|
469
|
-
|
233
|
+
getValue: function () {
|
234
|
+
'use strict';
|
235
|
+
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
470
236
|
},
|
471
237
|
|
472
|
-
|
473
|
-
|
238
|
+
// Trim and Strips HTML from text
|
239
|
+
sanitizeValue: function (s) {
|
240
|
+
'use strict';
|
241
|
+
return jQuery.trim(s);
|
474
242
|
},
|
475
243
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
244
|
+
/* Generate the data sent in the POST request */
|
245
|
+
requestData: function () {
|
246
|
+
'use strict';
|
247
|
+
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
248
|
+
var csrf_token = jQuery('meta[name=csrf-token]').attr('content'),
|
249
|
+
csrf_param = jQuery('meta[name=csrf-param]').attr('content');
|
480
250
|
|
481
|
-
|
482
|
-
|
483
|
-
this.collectionValue = !this.getValue();
|
484
|
-
this.setHtmlAttributes();
|
485
|
-
this.update();
|
486
|
-
},
|
251
|
+
var data = "_method=" + BestInPlaceEditor.defaults.ajaxMethod;
|
252
|
+
data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
|
487
253
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
"textarea" : {
|
494
|
-
activateForm : function() {
|
495
|
-
// grab width and height of text
|
496
|
-
width = this.element.css('width');
|
497
|
-
height = this.element.css('height');
|
498
|
-
|
499
|
-
// construct form
|
500
|
-
var output = jQuery(document.createElement('form'))
|
501
|
-
.attr('action', 'javascript:void(0)')
|
502
|
-
.attr('style', 'display:inline')
|
503
|
-
.append(jQuery(document.createElement('textarea'))
|
504
|
-
.val(this.sanitizeValue(this.display_value)));
|
505
|
-
if(this.okButton) {
|
506
|
-
output.append(
|
507
|
-
jQuery(document.createElement('input'))
|
508
|
-
.attr('type', 'submit')
|
509
|
-
.attr('value', this.okButton)
|
510
|
-
);
|
511
|
-
}
|
512
|
-
if(this.cancelButton) {
|
513
|
-
output.append(
|
514
|
-
jQuery(document.createElement('input'))
|
515
|
-
.attr('type', 'button')
|
516
|
-
.attr('value', this.cancelButton)
|
517
|
-
)
|
518
|
-
}
|
519
|
-
|
520
|
-
this.element.html(output);
|
521
|
-
this.setHtmlAttributes();
|
522
|
-
|
523
|
-
// set width and height of textarea
|
524
|
-
jQuery(this.element.find("textarea")[0]).css({ 'min-width': width, 'min-height': height });
|
525
|
-
jQuery(this.element.find("textarea")[0]).elastic();
|
526
|
-
|
527
|
-
this.element.find("textarea")[0].focus();
|
528
|
-
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
|
529
|
-
if (this.cancelButton) {
|
530
|
-
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
|
531
|
-
}
|
532
|
-
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
533
|
-
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
534
|
-
this.blurTimer = null;
|
535
|
-
this.userClicked = false;
|
254
|
+
if (csrf_param !== undefined && csrf_token !== undefined) {
|
255
|
+
data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
|
256
|
+
}
|
257
|
+
return data;
|
536
258
|
},
|
537
259
|
|
538
|
-
|
539
|
-
|
260
|
+
ajax: function (options) {
|
261
|
+
'use strict';
|
262
|
+
options.url = this.url;
|
263
|
+
options.beforeSend = function (xhr) {
|
264
|
+
xhr.setRequestHeader("Accept", "application/json");
|
265
|
+
};
|
266
|
+
return jQuery.ajax(options);
|
540
267
|
},
|
541
268
|
|
542
|
-
//
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
269
|
+
// Handlers ////////////////////////////////////////////////////////////////
|
270
|
+
|
271
|
+
loadSuccessCallback: function (data) {
|
272
|
+
'use strict';
|
273
|
+
data = jQuery.trim(data);
|
274
|
+
//Update original content with current text.
|
275
|
+
if (this.display_raw) {
|
276
|
+
this.original_content = this.element.html();
|
277
|
+
} else {
|
278
|
+
this.original_content = this.element.text();
|
279
|
+
}
|
280
|
+
|
281
|
+
if (data && data !== "") {
|
282
|
+
var response = jQuery.parseJSON(data);
|
283
|
+
if (response !== null && response.hasOwnProperty("display_as")) {
|
284
|
+
this.element.data('bip-original-content', this.element.text());
|
285
|
+
this.element.html(response.display_as);
|
555
286
|
}
|
556
|
-
|
287
|
+
|
288
|
+
this.element.trigger(jQuery.Event("best_in_place:success"), data);
|
289
|
+
this.element.trigger(jQuery.Event("ajax:success"), data);
|
557
290
|
} else {
|
558
|
-
|
291
|
+
this.element.trigger(jQuery.Event("best_in_place:success"));
|
292
|
+
this.element.trigger(jQuery.Event("ajax:success"));
|
293
|
+
}
|
294
|
+
// Binding back after being clicked
|
295
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
296
|
+
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
297
|
+
|
298
|
+
if (this.collectionValue !== null && this.formType === "select") {
|
299
|
+
this.collectionValue = this.previousCollectionValue;
|
300
|
+
this.previousCollectionValue = null;
|
559
301
|
}
|
560
|
-
}
|
561
302
|
},
|
562
303
|
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
304
|
+
loadErrorCallback: function (request, error) {
|
305
|
+
'use strict';
|
306
|
+
this.activateText(this.oldValue);
|
307
|
+
|
308
|
+
this.element.trigger(jQuery.Event("best_in_place:error"), [request, error]);
|
309
|
+
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
310
|
+
|
311
|
+
// Binding back after being clicked
|
312
|
+
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
313
|
+
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
567
314
|
},
|
568
315
|
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
event.stopPropagation(); // Without this, click isn't handled
|
316
|
+
clickHandler: function (event) {
|
317
|
+
'use strict';
|
318
|
+
event.preventDefault();
|
319
|
+
event.data.editor.activate();
|
574
320
|
},
|
575
321
|
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
}
|
580
|
-
}
|
581
|
-
}
|
582
|
-
};
|
322
|
+
setHtmlAttributes: function () {
|
323
|
+
'use strict';
|
324
|
+
var formField = this.element.find(this.formType);
|
583
325
|
|
584
|
-
|
326
|
+
if (this.html_attrs) {
|
327
|
+
var attrs = this.html_attrs;
|
328
|
+
$.each(attrs, function (key, val) {
|
329
|
+
formField.attr(key, val);
|
330
|
+
});
|
331
|
+
}
|
332
|
+
},
|
585
333
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
334
|
+
placeButtons: function (output, field) {
|
335
|
+
'use strict';
|
336
|
+
if (field.okButton) {
|
337
|
+
output.append(
|
338
|
+
jQuery(document.createElement('input'))
|
339
|
+
.attr('type', 'submit')
|
340
|
+
.attr('class', field.okButtonClass)
|
341
|
+
.attr('value', field.okButton)
|
342
|
+
);
|
343
|
+
}
|
344
|
+
if (field.cancelButton) {
|
345
|
+
output.append(
|
346
|
+
jQuery(document.createElement('input'))
|
347
|
+
.attr('type', 'button')
|
348
|
+
.attr('class', field.cancelButtonClass)
|
349
|
+
.attr('value', field.cancelButton)
|
350
|
+
);
|
351
|
+
}
|
590
352
|
}
|
591
|
-
|
353
|
+
};
|
592
354
|
|
593
|
-
jQuery(this.context).delegate(this.selector, 'click', function () {
|
594
|
-
var el = jQuery(this);
|
595
|
-
if (setBestInPlace(el))
|
596
|
-
el.click();
|
597
|
-
});
|
598
355
|
|
599
|
-
|
600
|
-
|
601
|
-
|
356
|
+
// Button cases:
|
357
|
+
// If no buttons, then blur saves, ESC cancels
|
358
|
+
// If just Cancel button, then blur saves, ESC or clicking Cancel cancels (careful of blur event!)
|
359
|
+
// If just OK button, then clicking OK saves (careful of blur event!), ESC or blur cancels
|
360
|
+
// If both buttons, then clicking OK saves, ESC or clicking Cancel or blur cancels
|
361
|
+
BestInPlaceEditor.forms = {
|
362
|
+
"input": {
|
363
|
+
activateForm: function () {
|
364
|
+
'use strict';
|
365
|
+
var output = jQuery(document.createElement('form'))
|
366
|
+
.addClass('form_in_place')
|
367
|
+
.attr('action', 'javascript:void(0);')
|
368
|
+
.attr('style', 'display:inline');
|
369
|
+
var input_elt = jQuery(document.createElement('input'))
|
370
|
+
.attr('type', 'text')
|
371
|
+
.attr('name', this.attributeName)
|
372
|
+
.val(this.display_value);
|
373
|
+
|
374
|
+
// Add class to form input
|
375
|
+
if (this.inner_class) {
|
376
|
+
input_elt.addClass(this.inner_class);
|
377
|
+
}
|
602
378
|
|
603
|
-
|
604
|
-
|
379
|
+
output.append(input_elt);
|
380
|
+
this.placeButtons(output, this);
|
605
381
|
|
382
|
+
this.element.html(output);
|
383
|
+
this.setHtmlAttributes();
|
606
384
|
|
385
|
+
this.element.find("input[type='text']")[0].select();
|
386
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
387
|
+
if (this.cancelButton) {
|
388
|
+
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
|
389
|
+
}
|
390
|
+
this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
391
|
+
this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
392
|
+
this.blurTimer = null;
|
393
|
+
this.userClicked = false;
|
394
|
+
},
|
395
|
+
|
396
|
+
getValue: function () {
|
397
|
+
'use strict';
|
398
|
+
return this.sanitizeValue(this.element.find("input").val());
|
399
|
+
},
|
400
|
+
|
401
|
+
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
402
|
+
inputBlurHandler: function (event) {
|
403
|
+
'use strict';
|
404
|
+
if (event.data.editor.okButton) {
|
405
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
406
|
+
if (!event.data.editor.userClicked) {
|
407
|
+
event.data.editor.abort();
|
408
|
+
}
|
409
|
+
}, 500);
|
410
|
+
} else {
|
411
|
+
if (event.data.editor.cancelButton) {
|
412
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
413
|
+
if (!event.data.editor.userClicked) {
|
414
|
+
event.data.editor.update();
|
415
|
+
}
|
416
|
+
}, 500);
|
417
|
+
} else {
|
418
|
+
event.data.editor.update();
|
419
|
+
}
|
420
|
+
}
|
421
|
+
},
|
422
|
+
|
423
|
+
submitHandler: function (event) {
|
424
|
+
'use strict';
|
425
|
+
event.data.editor.userClicked = true;
|
426
|
+
clearTimeout(event.data.editor.blurTimer);
|
427
|
+
event.data.editor.update();
|
428
|
+
},
|
429
|
+
|
430
|
+
cancelButtonHandler: function (event) {
|
431
|
+
'use strict';
|
432
|
+
event.data.editor.userClicked = true;
|
433
|
+
clearTimeout(event.data.editor.blurTimer);
|
434
|
+
event.data.editor.abort();
|
435
|
+
event.stopPropagation(); // Without this, click isn't handled
|
436
|
+
},
|
607
437
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
*
|
614
|
-
* @author Jan Jarfalk
|
615
|
-
* @author-email jan.jarfalk@unwrongest.com
|
616
|
-
* @author-website http://www.unwrongest.com
|
617
|
-
*
|
618
|
-
* @licens MIT License - http://www.opensource.org/licenses/mit-license.php
|
619
|
-
*/
|
620
|
-
|
621
|
-
(function(jQuery){
|
622
|
-
if (typeof jQuery.fn.elastic !== 'undefined') return;
|
623
|
-
|
624
|
-
jQuery.fn.extend({
|
625
|
-
elastic: function() {
|
626
|
-
// We will create a div clone of the textarea
|
627
|
-
// by copying these attributes from the textarea to the div.
|
628
|
-
var mimics = [
|
629
|
-
'paddingTop',
|
630
|
-
'paddingRight',
|
631
|
-
'paddingBottom',
|
632
|
-
'paddingLeft',
|
633
|
-
'fontSize',
|
634
|
-
'lineHeight',
|
635
|
-
'fontFamily',
|
636
|
-
'width',
|
637
|
-
'fontWeight'];
|
638
|
-
|
639
|
-
return this.each( function() {
|
640
|
-
|
641
|
-
// Elastic only works on textareas
|
642
|
-
if ( this.type != 'textarea' ) {
|
643
|
-
return false;
|
438
|
+
keyupHandler: function (event) {
|
439
|
+
'use strict';
|
440
|
+
if (event.keyCode === 27) {
|
441
|
+
event.data.editor.abort();
|
442
|
+
}
|
644
443
|
}
|
444
|
+
},
|
645
445
|
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
446
|
+
"select": {
|
447
|
+
activateForm: function () {
|
448
|
+
'use strict';
|
449
|
+
var output = jQuery(document.createElement('form'))
|
450
|
+
.attr('action', 'javascript:void(0)')
|
451
|
+
.attr('style', 'display:inline'),
|
452
|
+
selected = '',
|
453
|
+
select_elt = jQuery(document.createElement('select'))
|
454
|
+
.attr('class', this.inner_class !== null ? this.inner_class : ''),
|
455
|
+
currentCollectionValue = this.collectionValue;
|
456
|
+
|
457
|
+
jQuery.each(this.values, function (key, value) {
|
458
|
+
var option_elt = jQuery(document.createElement('option'))
|
459
|
+
.val(key)
|
460
|
+
.html(value);
|
461
|
+
if (key === String(currentCollectionValue)) {
|
462
|
+
option_elt.attr('selected', 'selected');
|
463
|
+
}
|
464
|
+
select_elt.append(option_elt);
|
465
|
+
});
|
466
|
+
output.append(select_elt);
|
467
|
+
|
468
|
+
this.element.html(output);
|
469
|
+
this.setHtmlAttributes();
|
470
|
+
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
471
|
+
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
472
|
+
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
473
|
+
this.element.find("select")[0].focus();
|
474
|
+
},
|
475
|
+
|
476
|
+
getValue: function () {
|
477
|
+
'use strict';
|
478
|
+
return this.sanitizeValue(this.element.find("select").val());
|
479
|
+
},
|
480
|
+
|
481
|
+
blurHandler: function (event) {
|
482
|
+
'use strict';
|
483
|
+
event.data.editor.update();
|
484
|
+
},
|
485
|
+
|
486
|
+
keyupHandler: function (event) {
|
487
|
+
'use strict';
|
488
|
+
if (event.keyCode === 27) {
|
489
|
+
event.data.editor.abort();
|
490
|
+
}
|
665
491
|
}
|
492
|
+
},
|
666
493
|
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
494
|
+
"checkbox": {
|
495
|
+
activateForm: function () {
|
496
|
+
'use strict';
|
497
|
+
this.collectionValue = !this.getValue();
|
498
|
+
this.setHtmlAttributes();
|
499
|
+
this.update();
|
500
|
+
},
|
501
|
+
|
502
|
+
getValue: function () {
|
503
|
+
'use strict';
|
504
|
+
return this.collectionValue;
|
675
505
|
}
|
506
|
+
},
|
676
507
|
|
508
|
+
"textarea": {
|
509
|
+
activateForm: function () {
|
510
|
+
'use strict';
|
511
|
+
// grab width and height of text
|
512
|
+
var width = this.element.css('width');
|
513
|
+
var height = this.element.css('height');
|
514
|
+
|
515
|
+
// construct form
|
516
|
+
var output = jQuery(document.createElement('form'))
|
517
|
+
.addClass('form_in_place')
|
518
|
+
.attr('action', 'javascript:void(0);')
|
519
|
+
.attr('style', 'display:inline');
|
520
|
+
var textarea_elt = jQuery(document.createElement('textarea'))
|
521
|
+
.val(this.sanitizeValue(this.display_value));
|
522
|
+
|
523
|
+
if (this.inner_class !== null) {
|
524
|
+
textarea_elt.addClass(this.inner_class);
|
525
|
+
}
|
677
526
|
|
678
|
-
|
679
|
-
function update() {
|
527
|
+
output.append(textarea_elt);
|
680
528
|
|
681
|
-
|
682
|
-
var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ /g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
|
529
|
+
this.placeButtons(output, this);
|
683
530
|
|
684
|
-
|
685
|
-
|
531
|
+
this.element.html(output);
|
532
|
+
this.setHtmlAttributes();
|
686
533
|
|
687
|
-
|
534
|
+
// set width and height of textarea
|
535
|
+
jQuery(this.element.find("textarea")[0]).css({'min-width': width, 'min-height': height});
|
536
|
+
jQuery(this.element.find("textarea")[0]).autosize();
|
688
537
|
|
689
|
-
|
690
|
-
|
538
|
+
this.element.find("textarea")[0].focus();
|
539
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
|
691
540
|
|
692
|
-
|
693
|
-
|
541
|
+
if (this.cancelButton) {
|
542
|
+
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
|
543
|
+
}
|
694
544
|
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
545
|
+
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
546
|
+
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
547
|
+
this.blurTimer = null;
|
548
|
+
this.userClicked = false;
|
549
|
+
},
|
550
|
+
|
551
|
+
getValue: function () {
|
552
|
+
'use strict';
|
553
|
+
return this.sanitizeValue(this.element.find("textarea").val());
|
554
|
+
},
|
555
|
+
|
556
|
+
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
557
|
+
blurHandler: function (event) {
|
558
|
+
'use strict';
|
559
|
+
if (event.data.editor.okButton) {
|
560
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
561
|
+
if (!event.data.editor.userClicked) {
|
562
|
+
event.data.editor.abortIfConfirm();
|
563
|
+
}
|
564
|
+
}, 500);
|
565
|
+
} else {
|
566
|
+
if (event.data.editor.cancelButton) {
|
567
|
+
event.data.editor.blurTimer = setTimeout(function () {
|
568
|
+
if (!event.data.editor.userClicked) {
|
569
|
+
event.data.editor.update();
|
570
|
+
}
|
571
|
+
}, 500);
|
572
|
+
} else {
|
573
|
+
event.data.editor.update();
|
574
|
+
}
|
575
|
+
}
|
576
|
+
},
|
577
|
+
|
578
|
+
submitHandler: function (event) {
|
579
|
+
'use strict';
|
580
|
+
event.data.editor.userClicked = true;
|
581
|
+
clearTimeout(event.data.editor.blurTimer);
|
582
|
+
event.data.editor.update();
|
583
|
+
},
|
584
|
+
|
585
|
+
cancelButtonHandler: function (event) {
|
586
|
+
'use strict';
|
587
|
+
event.data.editor.userClicked = true;
|
588
|
+
clearTimeout(event.data.editor.blurTimer);
|
589
|
+
event.data.editor.abortIfConfirm();
|
590
|
+
event.stopPropagation(); // Without this, click isn't handled
|
591
|
+
},
|
703
592
|
|
593
|
+
keyupHandler: function (event) {
|
594
|
+
'use strict';
|
595
|
+
if (event.keyCode === 27) {
|
596
|
+
event.data.editor.abortIfConfirm();
|
704
597
|
}
|
598
|
+
}
|
599
|
+
}
|
600
|
+
};
|
705
601
|
|
706
|
-
|
602
|
+
BestInPlaceEditor.defaults = {
|
603
|
+
locales: {},
|
604
|
+
ajaxMethod: "put", //TODO Change to patch when support to 3.2 is dropped
|
605
|
+
ajaxDataType: 'text',
|
606
|
+
okButtonClass: '',
|
607
|
+
cancelButtonClass: ''
|
608
|
+
};
|
707
609
|
|
708
|
-
|
610
|
+
// Default locale
|
611
|
+
BestInPlaceEditor.defaults.locales[''] = {
|
612
|
+
confirmMessage: "Are you sure you want to discard your changes?",
|
613
|
+
uninitializedForm: "The form was not properly initialized. getValue is unbound",
|
614
|
+
placeHolder: '-'
|
615
|
+
};
|
709
616
|
|
710
|
-
|
711
|
-
|
617
|
+
jQuery.fn.best_in_place = function () {
|
618
|
+
'use strict';
|
619
|
+
function setBestInPlace(element) {
|
620
|
+
if (!element.data('bestInPlaceEditor')) {
|
621
|
+
element.data('bestInPlaceEditor', new BestInPlaceEditor(element));
|
622
|
+
return true;
|
623
|
+
}
|
624
|
+
}
|
712
625
|
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
626
|
+
jQuery(this.context).delegate(this.selector, 'click', function () {
|
627
|
+
var el = jQuery(this);
|
628
|
+
if (setBestInPlace(el)) {
|
629
|
+
el.click();
|
630
|
+
}
|
631
|
+
});
|
717
632
|
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
if($twin.height() < maxheight){
|
722
|
-
if($twin.height() > minheight) {
|
723
|
-
$textarea.height($twin.height());
|
724
|
-
} else {
|
725
|
-
$textarea.height(minheight);
|
726
|
-
}
|
727
|
-
}
|
728
|
-
});
|
633
|
+
this.each(function () {
|
634
|
+
setBestInPlace(jQuery(this));
|
635
|
+
});
|
729
636
|
|
730
|
-
|
731
|
-
|
637
|
+
return this;
|
638
|
+
};
|
732
639
|
|
733
|
-
// Run update once when elastic is initialized
|
734
|
-
update();
|
735
640
|
|
736
|
-
});
|
737
641
|
|
738
|
-
}
|
739
|
-
});
|
740
|
-
})(jQuery);
|