rest_in_place 2.0.0.beta → 2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,11 +1,11 @@
1
1
  REST in Place
2
2
  ===========
3
- _______
4
- / \
5
- | R.I.P.|
6
- | |
7
- | |
8
- -------------
3
+ _______
4
+ / \
5
+ | R.I.P.|
6
+ | |
7
+ | |
8
+ -------------
9
9
 
10
10
  REST in Place is an AJAX Inplace-Editor that talks to RESTful controllers.
11
11
  It requires absolutely no additional server-side code if your controller
@@ -19,6 +19,7 @@ The editor works by PUTting the updated value to the server and GETting the
19
19
  updated record afterwards to display the updated value.
20
20
  That way any authentication methods or otherwise funky workflows in your
21
21
  controllers are used for the inplace-editors requests.
22
+
22
23
  To save the additional GET request, you can take the shortcut of returning the
23
24
  updated record in the response to the PUT request. See the testapp for an
24
25
  example.
@@ -33,17 +34,6 @@ If you like REST in Place, you can flattr me: <a href="http://flattr.com/thing/1
33
34
  Requirements
34
35
  ============
35
36
 
36
- JavaScript
37
- ----------
38
-
39
- The JavaScript code (`app/assets/javascripts/rest_in_place/rest_in_place.js.erb`)
40
- only relies on the presence of jQuery. You can extract just that file and use
41
- it with whatever framework in whatever server-side language you want, given
42
- that you follow the coventions described later in this document.
43
-
44
- Even though this is processed by ERB, you can use it as a JavaScript file
45
- without modification.
46
-
47
37
  Rails
48
38
  -----
49
39
 
@@ -56,12 +46,33 @@ version of jQuery. Just make sure that jQuery is there.
56
46
  REST in Place requires Rails >= 3.1 as a dependency since it loads through the
57
47
  asset pipeline.
58
48
 
49
+ CoffeeScript
50
+ ------------
51
+
52
+ The CoffeeScript code (`lib/assets/javascripts/rest_in_place/rest_in_place.coffee.erb`)
53
+ only relies on the presence of jQuery. You can extract just that file and use
54
+ it with whatever framework in whatever server-side language you want, given
55
+ that you follow the coventions described later in this document.
56
+
57
+ Even though this is processed by ERB to sniff out some relevant Rails settings,
58
+ you can use it as a CoffeeScript file without modification. (This feature
59
+ might vanish at any time in the future, tying RIP closer to Rails).
60
+
61
+ JavaScript only
62
+ ---------------
63
+
64
+ If you're still using JavaScript, give [CoffeeScript](http://jashkenas.github.com/coffee-script/)
65
+ a try. It's a preprocessor/different syntax, that makes writing JavaScript
66
+ bearable. If you absolutely don't want to learn anything new, just convert
67
+ REST in Place to JavaScript using http://js2coffee.org/ before including it in
68
+ your project.
69
+
59
70
  Installation
60
71
  ============
61
72
 
62
73
  Just add
63
74
 
64
- gem 'rest_in_place'
75
+ gem 'rest_in_place'
65
76
 
66
77
  to your Gemfile.
67
78
 
@@ -69,31 +80,29 @@ Then load the JavaScript by adding <%= javascript_include_tag "rest_in_place" %>
69
80
  into your layout. Alternatively you can require 'rest_in_place' in your
70
81
  JavaScript files in `app/assets`, for example in your application.js:
71
82
 
72
- //= require 'rest_in_place'
83
+ //= require 'rest_in_place'
73
84
 
74
85
  In both cases, make sure you load REST in Place __after__ jQuery.
75
86
 
76
87
  Rails Request forgery Protection
77
88
  ================================
78
89
 
79
- For REST in Place to work with Rails request forgery protection, place the
80
- following lines into your applications layout:
90
+ For REST in Place to work with Rails request forgery protection, you need to
91
+ have the Rails CSRF meta tags in your HTML head:
81
92
 
82
- <script type="text/javascript">
83
- rails_authenticity_token = '<%= form_authenticity_token %>'
84
- </script>
93
+ <%= csrf_meta_tags %>
85
94
 
86
95
  Usage Instructions
87
96
  ==================
88
97
 
89
98
  To make a piece of Text inplace-editable, wrap it into an element (a span
90
- usually) with class "rest_in_place". The editor needs 3 pieces of information
99
+ usually) with class "rest-in-place". The editor needs 3 pieces of information
91
100
  to work: a URL, an object name and the attribute name. These are provided as
92
101
  follows:
93
102
 
94
103
  - put attributes into the element, like this:
95
104
 
96
- <span class="rest_in_place" data-url="/users/1" data-object="user" data-attribute="name">
105
+ <span class="rest-in-place" data-url="/users/1" data-object="user" data-attribute="name">
97
106
  <%= @user.name %>
98
107
  </span>
99
108
 
@@ -101,8 +110,8 @@ follows:
101
110
  for them. That means you can write something like:
102
111
 
103
112
  <div data-object="user" data-url="/users/1">
104
- Name: <span class="rest_in_place" data-attribute="name" ><%= @user.name %></span><br/>
105
- eMail: <span class="rest_in_place" data-attribute="email"><%= @user.email %></span>
113
+ Name: <span class="rest-in-place" data-attribute="name" ><%= @user.name %></span><br/>
114
+ eMail: <span class="rest-in-place" data-attribute="email"><%= @user.email %></span>
106
115
  </div>
107
116
 
108
117
  - You can completely omit the url to use the current document's url.
@@ -114,8 +123,8 @@ follows:
114
123
  ActiveRecord for you. So, your HTML page may look like this:
115
124
 
116
125
  <div id="<%= dom_id @user # == "user_1" %>">
117
- Name: <span class="rest_in_place" data-attribute="name" ><%= @user.name %></span><br/>
118
- eMail: <span class="rest_in_place" data-attribute="email"><%= @user.email %></span>
126
+ Name: <span class="rest-in-place" data-attribute="name" ><%= @user.name %></span><br/>
127
+ eMail: <span class="rest-in-place" data-attribute="email"><%= @user.email %></span>
119
128
  </div>
120
129
 
121
130
  REST in Place recognizes dom_ids of this form and derives the object parameter
@@ -133,12 +142,18 @@ follows:
133
142
  To write your own form types, just extend the `RestInPlace.forms` object
134
143
  and select your new form type throught the `data-formtype` attribute.
135
144
 
145
+ Elements with the class `rest-in-place` are picked up automatically upon
146
+ `document.ready`. For other elements, grab them via jQuery and call
147
+ restInPlace() on the jQuery object.
148
+
149
+ $('.my-custom-class').restInPlace()
150
+
136
151
  Example
137
152
  =======
138
153
 
139
154
  Your routes.rb:
140
155
 
141
- map.resources :users
156
+ resources :users
142
157
 
143
158
  Your app/controllers/users_controller.rb:
144
159
 
@@ -155,7 +170,7 @@ Your app/controllers/users_controller.rb:
155
170
  @user = User.find params[:id]
156
171
  if @user.update_attributes!(params[:user])
157
172
  respond_to do |format|
158
- format.html { redirect_to( @person ) }
173
+ format.html { redirect_to( @person )}
159
174
  format.json { render :json => @user }
160
175
  end
161
176
  else
@@ -169,31 +184,18 @@ Your app/controllers/users_controller.rb:
169
184
 
170
185
  Your app/views/users/show.html.erb:
171
186
 
172
- <html>
173
- <head>
174
- <%= javascript_include_tag "jquery-1.4.min" , "jquery.rest_in_place" %>
175
- <script type="text/javascript">
176
- rails_authenticity_token = '<%= form_authenticity_token %>'
177
- jQuery(function(){
178
- jQuery(".rest_in_place").rest_in_place();
179
- });
180
- </script>
181
- </head>
182
- <body>
183
- <div id="<%= dom_id @user %>">
184
- ID: <%= @user.id %><br />
185
- Name: <span class="rest_in_place" data-formtype="input" data-attribute="name"><%= @user.name %></span><br/><br/>
186
- Hobbies: <span class="rest_in_place" data-formtype="textarea" data-attribute="hobbies"><%= @user.hobbies %></span>
187
- </div>
188
- </body>
189
- </html>
187
+ <div id="<%= dom_id @user %>">
188
+ ID: <%= @user.id %><br />
189
+ Name: <span class="rest-in-place" data-formtype="input" data-attribute="name"><%= @user.name %></span><br/><br/>
190
+ Hobbies: <span class="rest-in-place" data-formtype="textarea" data-attribute="hobbies"><%= @user.hobbies %></span>
191
+ </div>
190
192
 
191
193
  You can run this example by running to the testapp included in this
192
194
  plugin with script/server (sqlite3 required) and visiting
193
195
  localhost:3000/users/
194
196
 
195
197
  Hint:
196
- you need to set up the database first.
198
+ you might need to set up the database first.
197
199
  Copy and edit `testapp/config/database.yml.sample` accordingly.
198
200
  If you don't want to use the included sqlite3 database, run `rake db:create`
199
201
  and `rake db:schema:load`.
@@ -205,23 +207,31 @@ REST in Place is very picky about correct headers and formatting.
205
207
  If you experience errors, please make sure your controller sends responses as
206
208
  properly formatted JSON with the correct MIME-Type "application/json".
207
209
 
208
- Non-Rails
209
- =========
210
+ Testing
211
+ =======
210
212
 
211
- REST in Place was written for Ruby on Rails but is usable with any kind of
212
- RESTful web api. You should be able to adapt the instructions above to your
213
- framework easily.
213
+ The repository contains a `testapp` directory with a rails app that can be
214
+ used to test REST in Place. Just head to `http://localhost:3000` to see it in
215
+ action.
216
+
217
+ There's also an automated Jasmine spec suite running at
218
+ `http://localhost:3000/jasmine`. You can find the sources for the specs at
219
+ `testapp/app/assets/javascripts/spec.coffee`
214
220
 
215
221
  Participation
216
222
  =============
217
223
 
218
- I'd love to get comments, bug reports (or better, patches) about REST in Place.
219
- For this, you can either fork the project and send a pull request, or submit a
220
- bug in the tracker at github: <http://github.com/janv/rest_in_place/issues>
224
+ I'd love to get comments, bug reports (or better, pull-requests) about REST in
225
+ Place. For this, you can either fork the project to send a pull request, or
226
+ submit a bug in the tracker at github:
227
+ <http://github.com/janv/rest_in_place/issues>
221
228
 
222
229
  For general comments and questions, please use the comment function on my blog:
223
230
  <http://jan.varwig.org/projects/rest-in-place>
224
231
 
232
+ If you send pull requests be sure to also add tests and make sure the existing
233
+ tests pass.
234
+
225
235
 
226
236
  ---
227
- Copyright (c) 2010 [Jan Varwig], released under the MIT license
237
+ Copyright (c) 2011 [Jan Varwig], released under the MIT license
@@ -0,0 +1,213 @@
1
+ # # REST in Place Editor #####################################################
2
+ #
3
+ # This is the main class that manages the manipulation of the DOM and the AJAX
4
+ # requests
5
+ class RestInPlaceEditor
6
+ constructor : (e) ->
7
+ @$element = $(e)
8
+ @initOptions()
9
+ @bindForm()
10
+ @createClickHandler()
11
+
12
+ @$element.click(@clickHandler)
13
+
14
+ # ## Public interface functions ############################################
15
+
16
+ # Toggle the element associated with this editor from normal to a form field
17
+ activate : ->
18
+ @oldValue = @$element.html()
19
+ @$element.addClass('rip-active')
20
+ @$element.unbind('click', @clickHandler)
21
+ @activateForm()
22
+
23
+ # Restore the element to its default state
24
+ abort : ->
25
+ @$element
26
+ .html(@oldValue)
27
+ .removeClass('rip-active')
28
+ .click(@clickHandler)
29
+
30
+ # Take the changes a user has made and send them to the server.
31
+ # If the server accepted the request but does not send back a
32
+ # parseable answer, a second request is initiated to retrieve the updated
33
+ # value via GET
34
+ update : ->
35
+ updateRequest = @ajax
36
+ type : "post"
37
+ data : @requestData()
38
+
39
+ updateRequest.done (data) =>
40
+ if data
41
+ @loadSuccessCallback(data)
42
+ else
43
+ @loadViaGET()
44
+
45
+ updateRequest.fail (jqXHR, textStatus) =>
46
+ if (jqXHR.status == 200 && textStatus == "parsererror")
47
+ @loadViaGET()
48
+ else
49
+ @abort()
50
+
51
+ @$element.html("saving...")
52
+
53
+ loadViaGET : ->
54
+ showRequest = @ajax()
55
+ showRequest.done (data) => @loadSuccessCallback(data)
56
+
57
+ # ## Implementation Methods
58
+ #
59
+ # These are not implemented in RestInPlaceEditor. Instead, different form
60
+ # types implement this method (and some others). See [Forms](#forms)
61
+
62
+ # Turns the elements HTML into a form.
63
+ activateForm : ->
64
+ alert("The form was not properly initialized. activateForm is unbound")
65
+
66
+ # When the element is active (it is a form), thtis method returns the value
67
+ # that should be sent to the server.
68
+ getValue : ->
69
+ alert("The form was not properly initialized. getValue is unbound")
70
+
71
+ # ## Helper Functions ######################################################
72
+
73
+ # Derives configuration options from different sources:
74
+ #
75
+ # 1. Look through the chain of parent elements and search for data attributes
76
+ # 2. Try to guess the object name based on Rails id naming conventions if
77
+ # parents did not explicitly supply something
78
+ # 3. Take own data attributes, these always override other settings.
79
+ #
80
+ # These are the options:
81
+ #
82
+ # **data-url / @url**
83
+ # Where to send/receive data from
84
+ #
85
+ # **data-formtype / @formType**
86
+ # Which form extension to use (see [Forms](#forms))
87
+ #
88
+ # **data-object / @objectName**
89
+ # Rails singular lowercase name of the class of the objects. This is used
90
+ # to generate requests/parse responses that ActionController can understand.
91
+ #
92
+ # **data-attributes / @attributeName**
93
+ # Name of the attribute on the object. Combined with the object name to build
94
+ # query string parameters in the form `object[attribute]`, just as Rails
95
+ # expects it.
96
+ initOptions : ->
97
+ @$element.parents().each (index, parent) =>
98
+ @url = @url || $(parent).attr("data-url")
99
+ @formType = @formType || $(parent).attr("data-formtype")
100
+ @objectName = @objectName || $(parent).attr("data-object")
101
+ @attributeName = @attributeName || $(parent).attr("data-attribute")
102
+
103
+ @$element.parents().each (index, parent) =>
104
+ @objectName = @objectName || res[1] if res = parent.id.match(/^(\w+)_(\d+)$/i)
105
+
106
+ @url = @$element.attr("data-url") || @url || document.location.pathname
107
+ @formType = @$element.attr("data-formtype") || @formType || "input"
108
+ @objectName = @$element.attr("data-object") || @objectName
109
+ @attributeName = @$element.attr("data-attribute") || @attributeName
110
+
111
+ # Overwrites formtype specific method implementations during initialization
112
+ bindForm : ->
113
+ @activateForm = RestInPlaceEditor.forms[@formType].activateForm
114
+ @getValue = RestInPlaceEditor.forms[@formType].getValue
115
+
116
+ # Generate the data that is sent in the POST request
117
+ requestData : ->
118
+ data = @getEncodedTokenAuthenticationParams()
119
+ data["_method"] = 'put'
120
+ data["#{@objectName}[#{@attributeName}]"] = @getValue()
121
+ data
122
+
123
+ # Extract CSRF token from metatags
124
+ getEncodedTokenAuthenticationParams : ->
125
+ data = {}
126
+ param = $('meta[name=csrf-param]').attr('content')
127
+ token = $('meta[name=csrf-token]').attr('content')
128
+ data[param] = token if param && token
129
+ data
130
+
131
+ # A wrapper for jQuery.ajax
132
+ ajax : (options = {}) ->
133
+ options.url = @url
134
+ options.dataType = "json"
135
+ $.ajax(options)
136
+
137
+ # Extract the actual attribute value from the servers response
138
+ extractAttributeFromData : (data) ->
139
+ if @include_root_in_json
140
+ data[@objectName][@attributeName]
141
+ else
142
+ data[@attributeName]
143
+
144
+ # ## Handlers ##############################################################
145
+
146
+ # Handles the successful response from the server
147
+ loadSuccessCallback : (data) ->
148
+ @$element.html(@extractAttributeFromData(data))
149
+ @$element.click(@clickHandler)
150
+ @$element.removeClass('rip-active')
151
+
152
+ # Creates a clickhandler for the current instance of RestInPlaceEditor, that
153
+ # has its this pointer permanently bound to the editor instance.
154
+ createClickHandler : ->
155
+ @clickHandler = (event) => @activate()
156
+
157
+ # # <a name="forms">Forms</forms>
158
+ #
159
+ # Contains form type implementations. A form type implementation needs to
160
+ # provide two methods, `activateForm` and `getValue`, which are transplanted
161
+ # into the RestInPlaceEditor instance.
162
+ #
163
+ # `activateForm` : Turns the elements HTML into a form.
164
+ # `getValue` : When the element is active (it is a form), this method returns
165
+ # the value that should be sent to the server.
166
+ RestInPlaceEditor.forms =
167
+ "input" :
168
+ activateForm : ->
169
+ @$element.html("""<form action="javascript:void(0)" style="display:inline;"><input type="text" value="#{$.trim(@oldValue)}"></form>""")
170
+ @$element.find('input')[0].select()
171
+ @$element.find("form").submit =>
172
+ @update()
173
+ false
174
+ @$element.find("input").blur => @abort()
175
+
176
+ getValue : ->
177
+ @$element.find("input").val()
178
+
179
+ "textarea" :
180
+ activateForm : ->
181
+ @$element.html("""<form action="javascript:void(0)" style="display:inline;"><textarea>#{$.trim(@oldValue)}</textarea></form>""")
182
+ @$element.find('textarea')[0].select()
183
+ @$element.find("textarea").blur => @update()
184
+
185
+ getValue : ->
186
+ @$element.find("textarea").val()
187
+
188
+ # ------------------
189
+ #
190
+ # ### Support functionality
191
+
192
+ # Assign jQuery shortcut
193
+ $ = jQuery
194
+
195
+ # Detect Rails Settings
196
+ RestInPlaceEditor.prototype.include_root_in_json = "<%= ActiveRecord::Base.include_root_in_json %>" == "true"
197
+
198
+ # Install in global namespace
199
+ window.RestInPlaceEditor = RestInPlaceEditor
200
+
201
+ # Create jQuery function
202
+ # Use this to setup REST in Place functionality for elements of your page,
203
+ # for example:
204
+ #
205
+ # jQuery(".rest-in-place").restInPlace();
206
+ $.fn.restInPlace = ->
207
+ @each ->
208
+ $(this).data('restInPlaceEditor', new RestInPlaceEditor(this))
209
+ return this
210
+
211
+
212
+ # Run automatically
213
+ $ -> $('.rest-in-place').restInPlace()
@@ -1,3 +1,3 @@
1
1
  module RestInPlace
2
- VERSION = "2.0.0.beta"
2
+ VERSION = "2.0"
3
3
  end
@@ -5,7 +5,7 @@ require "rest_in_place/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "rest_in_place"
7
7
  s.version = RestInPlace::VERSION
8
- s.date = '2011-11-27'
8
+ s.date = '2011-12-03'
9
9
  s.authors = ["Jan Varwig"]
10
10
  s.email = ["jan@varwig.org"]
11
11
  s.homepage = "http://jan.varwig.org"
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.description = %q{REST in Place is an AJAX Inplace-Editor that talks to RESTful controllers.}
14
14
  s.license = "MIT"
15
15
 
16
- s.files = Dir["Gemfile", "MIT-LICENSE", "README.markdown", "rest_in_place.gemspec", "app/**/*", "lib/**/*"]
16
+ s.files = Dir["Gemfile", "MIT-LICENSE", "README.markdown", "rest_in_place.gemspec", "lib/**/*"]
17
17
 
18
18
  s.require_paths = ["lib"]
19
19
  s.add_dependency('rails', '>= 3.1')
metadata CHANGED
@@ -1,14 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest_in_place
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31098209
5
- prerelease: 6
4
+ hash: 3
5
+ prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 0
10
- - beta
11
- version: 2.0.0.beta
9
+ version: "2.0"
12
10
  platform: ruby
13
11
  authors:
14
12
  - Jan Varwig
@@ -16,7 +14,7 @@ autorequire:
16
14
  bindir: bin
17
15
  cert_chain: []
18
16
 
19
- date: 2011-11-27 00:00:00 Z
17
+ date: 2011-12-03 00:00:00 Z
20
18
  dependencies:
21
19
  - !ruby/object:Gem::Dependency
22
20
  name: rails
@@ -46,8 +44,8 @@ files:
46
44
  - MIT-LICENSE
47
45
  - README.markdown
48
46
  - rest_in_place.gemspec
49
- - app/assets/javascripts/rest_in_place/index.js
50
- - app/assets/javascripts/rest_in_place/rest_in_place.js.erb
47
+ - lib/assets/javascripts/rest_in_place/index.js
48
+ - lib/assets/javascripts/rest_in_place/rest_in_place.coffee.erb
51
49
  - lib/rest_in_place/version.rb
52
50
  - lib/rest_in_place.rb
53
51
  homepage: http://jan.varwig.org
@@ -70,14 +68,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
68
  required_rubygems_version: !ruby/object:Gem::Requirement
71
69
  none: false
72
70
  requirements:
73
- - - ">"
71
+ - - ">="
74
72
  - !ruby/object:Gem::Version
75
- hash: 25
73
+ hash: 3
76
74
  segments:
77
- - 1
78
- - 3
79
- - 1
80
- version: 1.3.1
75
+ - 0
76
+ version: "0"
81
77
  requirements: []
82
78
 
83
79
  rubyforge_project:
@@ -1,193 +0,0 @@
1
- function RestInPlaceEditor(e) {
2
- this.element = jQuery(e);
3
- this.initOptions();
4
- this.bindForm();
5
-
6
- this.element.bind('click', {editor: this}, this.clickHandler);
7
- }
8
-
9
- RestInPlaceEditor.prototype = {
10
- // Public Interface Functions //////////////////////////////////////////////
11
-
12
- activate : function() {
13
- this.oldValue = this.element.html();
14
- this.element.addClass('rip-active');
15
- this.element.unbind('click', this.clickHandler)
16
- this.activateForm();
17
- },
18
-
19
- abort : function() {
20
- this.element
21
- .html(this.oldValue)
22
- .removeClass('rip-active')
23
- .bind('click', {editor: this}, this.clickHandler);
24
- },
25
-
26
- update : function() {
27
- var editor = this;
28
- editor.ajax({
29
- "type" : "post",
30
- "dataType" : "json",
31
- "data" : editor.requestData(),
32
- "error" : function(response) {
33
- if (response.status == 100 && response.statusText == "parsererror") {
34
- editor.ajax({
35
- "dataType" : 'json',
36
- "success" : function(data){ editor.loadSuccessCallback(data) }
37
- });
38
- } else {
39
- editor.abort();
40
- }
41
- },
42
- "success" : function(data){
43
- if (data) {
44
- editor.loadSuccessCallback(data)
45
- } else {
46
- editor.ajax({
47
- "dataType" : 'json',
48
- "success" : function(data){ editor.loadSuccessCallback(data) }
49
- });
50
- }
51
- }
52
- });
53
- editor.element.html("saving...");
54
- },
55
-
56
- activateForm : function() {
57
- alert("The form was not properly initialized. activateForm is unbound");
58
- },
59
-
60
- // Helper Functions ////////////////////////////////////////////////////////
61
-
62
- initOptions : function() {
63
- // Try parent supplied info
64
- var self = this;
65
- self.element.parents().each(function(){
66
- self.url = self.url || jQuery(this).attr("data-url");
67
- self.formType = self.formType || jQuery(this).attr("data-formtype");
68
- self.objectName = self.objectName || jQuery(this).attr("data-object");
69
- self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
70
- });
71
- // Try Rails-id based if parents did not explicitly supply something
72
- self.element.parents().each(function(){
73
- var res;
74
- if (res = this.id.match(/^(\w+)_(\d+)$/i)) {
75
- self.objectName = self.objectName || res[1];
76
- }
77
- });
78
- // Load own attributes (overrides all others)
79
- self.url = self.element.attr("data-url") || self.url || document.location.pathname;
80
- self.formType = self.element.attr("data-formtype") || self.formtype || "input";
81
- self.objectName = self.element.attr("data-object") || self.objectName;
82
- self.attributeName = self.element.attr("data-attribute") || self.attributeName;
83
- },
84
-
85
- bindForm : function() {
86
- this.activateForm = RestInPlaceEditor.forms[this.formType].activateForm;
87
- this.getValue = RestInPlaceEditor.forms[this.formType].getValue;
88
- },
89
-
90
- getValue : function() {
91
- alert("The form was not properly initialized. getValue is unbound");
92
- },
93
-
94
- /* Generate the data sent in the POST request */
95
- requestData : function() {
96
- var data = "_method=put";
97
- data += "&"+this.objectName+'['+this.attributeName+']='+encodeURIComponent(this.getValue());
98
- data += this.getEncodedTokenAuthentication()
99
- return data;
100
- },
101
-
102
- getEncodedTokenAuthentication : function() {
103
- var param = $('meta[name=csrf-param]').attr('content');
104
- var token = $('meta[name=csrf-token]').attr('content');
105
- if (param && token) {
106
- param = encodeURIComponent(param);
107
- token = encodeURIComponent(token);
108
- return "&"+param+"="+token;
109
- } else {
110
- return "";
111
- }
112
- },
113
-
114
- ajax : function(options) {
115
- options.url = this.url;
116
- return jQuery.ajax(options);
117
- },
118
-
119
- extractAttributeFromData : function(data) {
120
- var include_root_in_json = "<%= ActiveRecord::Base.include_root_in_json %>";
121
- if (include_root_in_json == "false") {
122
- return data[this.attributeName];
123
- } else {
124
- return data[this.objectName][this.attributeName];
125
- }
126
- },
127
-
128
- // Handlers ////////////////////////////////////////////////////////////////
129
-
130
- loadSuccessCallback : function(data) {
131
- this.element.html(this.extractAttributeFromData(data));
132
- this.element.bind('click', {editor: this}, this.clickHandler);
133
- this.element.removeClass('rip-active');
134
- },
135
-
136
- clickHandler : function(event) {
137
- event.data.editor.activate();
138
- }
139
- };
140
-
141
-
142
- RestInPlaceEditor.forms = {
143
- "input" : {
144
- /* is bound to the editor and called to replace the element's content with a form for editing data */
145
- activateForm : function() {
146
- this.element.html('<form action="javascript:void(0)" style="display:inline;"><input type="text" value="' + jQuery.trim(this.oldValue) + '"></form>');
147
- this.element.find('input')[0].select();
148
- this.element.find("form")
149
- .bind('submit', {editor: this}, RestInPlaceEditor.forms.input.submitHandler);
150
- this.element.find("input")
151
- .bind('blur', {editor: this}, RestInPlaceEditor.forms.input.inputBlurHandler);
152
- },
153
-
154
- getValue : function() {
155
- return this.element.find("input").val();
156
- },
157
-
158
- inputBlurHandler : function(event) {
159
- event.data.editor.abort();
160
- },
161
-
162
- submitHandler : function(event) {
163
- event.data.editor.update();
164
- return false;
165
- }
166
- },
167
-
168
- "textarea" : {
169
- /* is bound to the editor and called to replace the element's content with a form for editing data */
170
- activateForm : function() {
171
- this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + jQuery.trim(this.oldValue) + '</textarea></form>');
172
- this.element.find('textarea')[0].select();
173
- this.element.find("textarea")
174
- .bind('blur', {editor: this}, RestInPlaceEditor.forms.textarea.blurHandler);
175
- },
176
-
177
- getValue : function() {
178
- return this.element.find("textarea").val();
179
- },
180
-
181
- blurHandler : function(event) {
182
- event.data.editor.update();
183
- }
184
-
185
- }
186
- };
187
-
188
- jQuery.fn.rest_in_place = function() {
189
- this.each(function(){
190
- jQuery(this).data('restInPlaceEditor', new RestInPlaceEditor(this));
191
- })
192
- return this;
193
- };