assetable 0.1.10 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/README.rdoc +9 -7
  3. data/app/assets/javascripts/assetable/assetable.js.coffee +16 -0
  4. data/app/assets/javascripts/assetable/assetable_uploader.js.coffee +40 -118
  5. data/app/assets/javascripts/assetable/gallery.js.coffee +12 -10
  6. data/app/assets/javascripts/assetable/uploader.js.coffee +27 -11
  7. data/app/assets/javascripts/vendor/jquery-ui-1.10.3.custom.js +285 -19
  8. data/app/assets/stylesheets/assetable/components/_gallery.css.sass +31 -0
  9. data/app/assets/stylesheets/assetable/components/_uploader.css.sass +2 -2
  10. data/app/assets/stylesheets/assetable/core/_utilities.css.sass +5 -1
  11. data/app/controllers/assetable/assets_controller.rb +19 -10
  12. data/app/controllers/assetable/external_services_controller.rb +9 -5
  13. data/app/helpers/assetable/asset_helper.rb +7 -0
  14. data/app/inputs/gallery_input.rb +28 -0
  15. data/app/inputs/uploader_input.rb +24 -0
  16. data/app/models/asset_attachment.rb +27 -0
  17. data/app/models/gallery.rb +3 -1
  18. data/app/views/assetable/assets/_asset.html.haml +30 -21
  19. data/app/views/assetable/assets/_directions.html.haml +9 -0
  20. data/app/views/assetable/assets/_form.html.haml +3 -5
  21. data/app/views/assetable/assets/_table.html.haml +22 -0
  22. data/app/views/assetable/assets/create.js.erb +7 -0
  23. data/app/views/assetable/assets/edit.js.erb +1 -0
  24. data/app/views/assetable/assets/index.js.erb +18 -0
  25. data/app/views/assetable/assets/insert.js.erb +9 -0
  26. data/app/views/assetable/assets/update.js.erb +2 -0
  27. data/app/views/assetable/external_services/_form.html.haml +3 -2
  28. data/app/views/assetable/external_services/create.js.erb +9 -0
  29. data/app/views/assetable/external_services/new.js.erb +1 -0
  30. data/app/views/assetable/shared/_asset_preview.html.haml +21 -0
  31. data/app/views/assetable/shared/templates/_asset_item.html.haml +29 -0
  32. data/app/views/assetable/shared/templates/_gallery_item.html.haml +42 -0
  33. data/config/initializers/uploader_input.rb +1 -1
  34. data/config/routes.rb +3 -1
  35. data/db/migrate/20140220053656_add_sort_order_to_asset_attachments.rb +15 -0
  36. data/lib/assetable.rb +6 -3
  37. data/lib/assetable/{core.rb → active_record/base.rb} +2 -2
  38. data/lib/assetable/inputs/uploaders.rb +27 -0
  39. data/lib/assetable/version.rb +1 -1
  40. metadata +40 -10
  41. data/app/views/assetable/assets/edit.html.haml +0 -1
  42. data/app/views/assetable/external_services/new.html.haml +0 -1
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTFjYWI5NzVhMGUzYjhiNjEzMDdmNzJkYmYzY2ZjZDQyMDQ4ZjY4OQ==
4
+ M2ZiYjc4YjE3M2Q5MmU4OWNlOTc3OGM2MWUzZThhMmUyOTNiOGUyZg==
5
5
  data.tar.gz: !binary |-
6
- YWM4OTJiYjY3NWNmODZiODdmNmI1NTZkN2Y1OTM1Y2RkOWY5YmQ4MA==
6
+ MmFmOWFmZDE5YTEwZTZlZTNhYzNiNGNjOWJmMDNkYTEyMGNmMjRlNA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YzljYzI4YzE2YWJhOGE1MWNlYTg5YmIxMWI2NmRiZWY1ZjU2YTA4OThmOGUx
10
- ZDZhZWU2MGYzYzE0NTVkODYwZmZlOWFkOGI4NjczMjFiYzc4NWI5Y2FkMTBm
11
- YjM0YzEyMzAxMWQ4MTkwNGVhM2FmOWQ2YmZjYWNhMjhiYWI1YTA=
9
+ YjlmODEyNDc5NTM5ZTk3NDE1NDEzNTlhN2QwZGIyNzE0YTI0MGQ0YmEwY2Uy
10
+ ZDc3Njk0NGRiNTZjZWM5MWQ0MWE3YTM0MjY3MTdhZDlhYWMwYmE5NTVlYWE3
11
+ NTQyZGQxMTdmZGZiYzA4YjMzNmQxNzMyMGQzNDhiNjQ4M2NmMDc=
12
12
  data.tar.gz: !binary |-
13
- ZTZiZGNiMWQyOGJiYzJhYTE3NjViNWI2OWFiYzYzNGI1NmM4OGI5ZmI0NTQx
14
- MzJkN2MwMGI0ZmZkYTY1MWNlZGZiODJiNTk5ZDQzYTI1MjE1ZTliYjlkMjk0
15
- ZjBlMzdjMzVlYTdjYmZiNGExZjRlZGNhMTg0MDVlMTE4N2FiY2E=
13
+ YjliMzQ3MDljMzdlZGM3MjgwNWU3MzVmY2ZhNGEwN2QzYjRhZTg0Y2M0NzU4
14
+ Y2UzNDUxMWE3MjFlNWVkN2RjOGIzZDkzM2VhN2MwYzgxYWYzNGFkOThlYjJl
15
+ YjY4Y2I0OWRlZDMzYzJhNmI3YTU4MTllNTg1MTM2NTdjMzA2NTU=
@@ -1,6 +1,8 @@
1
1
  = Assetable
2
2
 
3
- Easily add Assets to your Active Record models, including images, videos and almost any kind of documents. Includes an uploader, media gallery and much more.
3
+ Easily add Assets to your Rails app, including images, videos and almost any kind of documents. Includes an uploader, media gallery and much more.
4
+
5
+ This is still an early beta release. While the majority of uploading works, the media gallery selector is still in an early alpha.
4
6
 
5
7
  === Installation
6
8
 
@@ -8,7 +10,7 @@ Easily add Assets to your Active Record models, including images, videos and alm
8
10
 
9
11
  Add this line to your application's Gemfile:
10
12
 
11
- gem 'bootstrap_sass_rails'
13
+ gem 'assetable'
12
14
 
13
15
  And then execute:
14
16
 
@@ -16,7 +18,7 @@ And then execute:
16
18
 
17
19
  Or install it yourself as:
18
20
 
19
- $ gem install bootstrap_sass_rails
21
+ $ gem install assetable
20
22
 
21
23
 
22
24
  ==== Migrations
@@ -38,7 +40,7 @@ Add the Stylesheet and Javascripts to your project:
38
40
 
39
41
  Javascript:
40
42
 
41
- //= import uploader
43
+ //= require assetable/assetable
42
44
 
43
45
 
44
46
  ==== Configuration
@@ -152,12 +154,12 @@ In order to start uploading assets, you'll need to add the uploader to your form
152
154
 
153
155
  = form_for @user do |f|
154
156
  ...
155
- = f.uploader :avatar
157
+ = f.input :avatar, as: :uploader
156
158
  ...
157
159
 
158
160
  # You can also pass typical params to the uploader
159
161
  = form_for @user do |f|
160
- = f.uploader :avatar, class: "classname", id: "something-else"
162
+ = f.inputer :avatar, as: :uploader, input_html: { class: "classname", id: "something-else" }
161
163
 
162
164
  Make sure the assetable uploader javascript is added.
163
165
 
@@ -166,7 +168,7 @@ Make sure the assetable uploader javascript is added.
166
168
 
167
169
  = form_for @user do |f|
168
170
  ...
169
- = f.gallery :gallery
171
+ = f.input :gallery, as: :gallery
170
172
  ...
171
173
 
172
174
  It's that easy!
@@ -0,0 +1,16 @@
1
+ #= require_self
2
+
3
+ #= require moxie
4
+ #= require plupload.dev
5
+ #= require plupload.settings
6
+ #= require jquery.plupload.queue
7
+ #= require vendor/jquery-ui-1.10.3.custom
8
+ #= require vendor/bootstrap-modal
9
+
10
+
11
+ #= require assetable/assetable_uploader
12
+ #= require assetable/uploader
13
+ #= require assetable/gallery
14
+ #= require assetable/asset_gallery
15
+
16
+ window.Assetable = {}
@@ -19,37 +19,47 @@
19
19
  max_file_count: 0
20
20
  unique_names: true
21
21
  url: null
22
+ uploader_id: null
22
23
 
23
24
  assetable_uploader = this
24
25
 
25
26
  init = ->
26
27
  # merge the options with the defaults
27
28
  assetable_uploader.options = jQuery.extend({}, defaults, options)
28
- assetable_uploader.id = assetable_uploader.attr('id')
29
+
30
+ hidden_field = $(assetable_uploader).find('input[type="hidden"].assetable-uploader-input')
31
+ assetable_uploader.options.fieldname = hidden_field.attr('name')
32
+ assetable_uploader.options.uploader_id = hidden_field.attr('id')
33
+ $(hidden_field, assetable_uploader).remove() if assetable_uploader.options.gallery
34
+
35
+ $(assetable_uploader).attr('id', assetable_uploader.options.uploader_id)
36
+ $(assetable_uploader).find('.browse-btn').attr('id', "#{assetable_uploader.options.uploader_id}-browse-btn")
37
+ $(assetable_uploader).find('.drop-element').attr('id', "#{assetable_uploader.options.uploader_id}-drop-element")
38
+
39
+ # Add parameters to third party button
40
+ third_party_btn = $(assetable_uploader).find('.btn-third-party')
41
+ $(third_party_btn).attr('href', $(third_party_btn).attr('href') + "?fieldname=#{assetable_uploader.options.fieldname}&uploader_id=#{assetable_uploader.options.uploader_id}")
42
+
29
43
  bind_uploader()
30
44
 
31
45
 
32
46
  bind_uploader = ->
33
47
 
34
48
  # Create our extra HTML for the copy and queu
35
- # upload_directions = '<div class="uploader-directions" id="' + assetable_uploader.id + '-drop-area"><div class="uploader-directions-image"></div><div class="uploader-directions-copy">Drag and drop files or <a href="#" class="browse-btn" id="' + assetable_uploader.id + '-browse-btn">add them manually</a></div></div>'
36
- # upload_directions = '<div class="uploader-directions" id="' + assetable_uploader.id + '-drop-area"><div class="uploader-directions-image"></div><div class="uploader-directions-copy"><a href="#" class="browse-btn" id="' + assetable_uploader.id + '-browse-btn">select file</a> or <a href="#" class="btn-open-asset-gallery">open gallery</a></div></div>'
37
- upload_directions = '<div class="uploader-directions" id="' + assetable_uploader.id + '-drop-area"><div class="uploader-directions-image"></div><div class="uploader-directions-copy"><a href="#" class="browse-btn" id="' + assetable_uploader.id + '-browse-btn">select file</a> ' + assetable_uploader.options.directions + '</div></div>'
38
49
  upload_queue = '<ul class="upload-queue"></ul>'
39
50
  # Add to the uploader
40
- $(assetable_uploader).append(upload_directions)
41
51
  $(assetable_uploader).append(upload_queue)
42
52
 
43
53
 
44
54
  # Instantiate the uploader
45
55
  uploader = new plupload.Uploader(
46
56
  runtimes: "html5"
47
- browse_button: "#{assetable_uploader.id}-browse-btn"
57
+ browse_button: "#{assetable_uploader.options.uploader_id}-browse-btn"
48
58
  url: assetable_uploader.options.url
49
59
  max_file_size: assetable_uploader.options.max_file_size
50
60
  unique_names: assetable_uploader.options.unique_names
51
61
  dragdrop: assetable_uploader.options.drag_drop
52
- drop_element: assetable_uploader.id
62
+ drop_element: assetable_uploader.options.uploader_id
53
63
  multiple_queues: assetable_uploader.options.multiple_queues
54
64
  multi_selection: assetable_uploader.options.multi_selection
55
65
  max_file_count: assetable_uploader.options.max_file_count
@@ -57,27 +67,26 @@
57
67
  multipart_params:
58
68
  authenticity_token: assetable_uploader.options.authenticity_token
59
69
  fieldname: assetable_uploader.options.fieldname
70
+ gallery: assetable_uploader.options.gallery
71
+ uploader_id: assetable_uploader.options.uploader_id
60
72
 
61
73
  # Filter file types
62
- # filter: [
63
- # title: "Image files"
64
- # extensions: "jpg,gif,png"
65
- # ,
66
- # title: "Video files"
67
- # extensions: "mov,mp4,mpeg4"
68
- # ]
74
+ filters:
75
+ mime_types : [
76
+ title: "Image files"
77
+ extensions: "jpg,gif,png"
78
+ ,
79
+ title: "Video files"
80
+ extensions: "mov,mp4,mpeg4"
81
+ ,
82
+ title: "Zip Files"
83
+ extensions: "zip"
84
+ ]
85
+ max_file_size: assetable_uploader.options.max_file_size
86
+ prevent_duplicates: true
69
87
  )
70
88
 
71
89
 
72
-
73
- # # Uploader Template
74
- # template = "<div class=\"current_preview current_" + uploader_id + "\">" + content + "</div>" + "<div class=\"koh_pluploader\" id=\"" + uploader_id + "_drop_area\">" + "<a id=\"" + uploader_id + "_browse_btn\" href=\"#\"><span class=\"link_color\">Attach files by dragging & dropping them here</span> or add them manually</a>" + "<ul class=\"upload_queue\"></ul>" + "</div>" + ((if allow_select_mg then "<a href=\"#\" class=\"attach_image\" uid=\"" + uploader_id + "\" target=\"" + container + "\">select from media gallery</a>" else ""))
75
-
76
- # # Initialize binding
77
- # uploader.bind "Init", (up, params) ->
78
- # $("#" + container).html template
79
-
80
-
81
90
  # # Initiate the uploader
82
91
  uploader.init()
83
92
 
@@ -94,9 +103,7 @@
94
103
 
95
104
  # Listen for upload complete
96
105
  uploader.bind "FileUploaded", (up, file, info) ->
97
- if assetable_uploader.options.FileUploaded
98
- json = jQuery.parseJSON(info.response)
99
- assetable_uploader.options.FileUploaded json
106
+ eval(info.response)
100
107
  $("li#" + file.id, assetable_uploader).fadeOut().remove()
101
108
 
102
109
 
@@ -104,10 +111,11 @@
104
111
  uploader.bind "QueueChanged", (up, files) ->
105
112
  uploader.start()
106
113
  up.refresh()
114
+
107
115
  # # Listen for errors
108
- # uploader.bind "Error", (up, err) ->
109
- # $("#" + container).append "<div class=\"notice error\">" + "<span class=\"block\">Error: " + err.code + "</div>" + "<span class=\"block\">Message: " + err.message + "</div>" + ((if err.file then "<span clas=\"block\">" + err.file.name + "</span>" else "")) + "</div>"
110
- # up.refresh() # Reposition Flash/Silverlight
116
+ uploader.bind "Error", (up, err) ->
117
+
118
+
111
119
 
112
120
  draggable_selector = (if assetable_uploader.options.gallery then $('.uploader-directions', assetable_uploader) else $(assetable_uploader))
113
121
 
@@ -132,27 +140,8 @@
132
140
  $(assetable_uploader).on "click", ".btn-uploader-remove-asset", (e)->
133
141
  e.preventDefault()
134
142
  if assetable_uploader.options.fileRemoved
135
- assetable_uploader.options.fileRemoved this, assetable_uploader
136
-
137
-
138
- $(assetable_uploader).on "click", ".btn-uploader-edit-asset", (e)->
139
- e.preventDefault()
140
- $.ajax
141
- url: $(this).attr('href')
142
- data: {fieldname: assetable_uploader.options.fieldname}
143
- type: 'GET'
143
+ assetable_uploader.options.fileRemoved assetable_uploader, this
144
144
 
145
- success: (response)->
146
- $response = $(response)
147
- $response.modal()
148
-
149
- $('form.form-edit-asset').on 'ajax:beforeSend', ()->
150
- # console.log "form submitting..."
151
-
152
- $('form.form-edit-asset').on 'ajax:success', (data, status, xhr)->
153
- if status.success
154
- $response.modal('hide').remove()
155
- assetable_uploader.options.fileUpdated status
156
145
 
157
146
 
158
147
  $(assetable_uploader).on "click", ".btn-open-asset-gallery", (e)->
@@ -161,75 +150,8 @@
161
150
  # if assetable_uploader.options.openAssetGallery
162
151
  # assetable_uploader.options.openAssetGallery this, assetable_uploader
163
152
 
164
- # $(assetable_uploader).on "click", ".btn-third-party-service", (e)->
165
- # e.preventDefault()
166
- # console.log "boom"
167
-
168
-
169
- # Add a third party service
170
- $(assetable_uploader).on "click", ".btn-third-party-service", (e)->
171
- e.preventDefault()
172
- $.ajax
173
- url: $(this).attr('href')
174
- data: {fieldname: assetable_uploader.options.fieldname}
175
- type: 'GET'
176
-
177
- success: (response)->
178
- $response = $(response)
179
- $response.modal()
180
-
181
- $('form#new_external_service').on 'ajax:beforeSend', ()->
182
- # console.log "form submitting..."
183
-
184
- $('form#new_external_service').on 'ajax:success', (data, status, xhr)->
185
- if status.success
186
- $response.modal('hide').remove()
187
- assetable_uploader.options.FileUploaded status
188
-
189
-
190
-
191
-
153
+
192
154
 
193
155
  init()
194
156
 
195
- ) jQuery
196
-
197
-
198
-
199
-
200
- bind_uploaders = ->
201
- # Bind the koh uploader and galleries to a page
202
- $(".uploader").each ->
203
- # Check that it's not already bound
204
- unless $(this).hasClass("uploadable")
205
- $(this).addClass "uploadable"
206
- $this = $(this)
207
- $this.removeClass "uploader"
208
-
209
- field = $this.attr("data-uploader-input-name")
210
-
211
- $this.assetable_uploader
212
- multi_selection: false
213
- url: "/assetable/assets"
214
- fieldname: field
215
- directions: $this.attr('data-uploader-directions')
216
- max_file_size: $this.attr("data-max-file-size")
217
- authenticity_token: $("meta[name=\"csrf-token\"]").attr("content")
218
- onUploaded: (resp) ->
219
- $this.find('.uploader-data-wrapper').html(resp.html)
220
- $this.addClass("uploader-has-asset")
221
- fileRemoved: (button, item) ->
222
- return false unless $(item).hasClass("uploader-has-asset")
223
- $('.uploader-preview', item).html('<input type="hidden" name="' + field + '" />')
224
- $(item).removeClass("uploader-has-asset")
225
- fileUpdated: (resp) ->
226
- $this.find('div.uploader-preview[data-asset-id="' + resp.id + '"]').replaceWith(resp.html)
227
- # openAssetGallery: (button, item) ->
228
-
229
-
230
-
231
- window.Assetable.bind_uploaders = bind_uploaders
232
-
233
- $(document).ready ->
234
-
235
- window.Assetable.bind_uploaders()
157
+ ) jQuery
@@ -1,4 +1,5 @@
1
1
  bind_galleries = ->
2
+
2
3
  # Bind the koh uploader and galleries to a page
3
4
  $(".gallery-uploader").each ->
4
5
  # Check that it's not already bound
@@ -6,21 +7,16 @@ bind_galleries = ->
6
7
  $(this).addClass "uploadable"
7
8
  $this = $(this)
8
9
  $this.removeClass "uploader"
9
-
10
- field = $this.attr("data-uploader-input-name")
11
10
 
12
11
  $this.assetable_uploader
13
12
  multi_selection: true
14
13
  gallery: true
15
- url: "/assetable/assets"
16
- fieldname: field
14
+ url: "/assetable/assets.js"
17
15
  authenticity_token: $("meta[name=\"csrf-token\"]").attr("content")
18
- onUploaded: (resp) ->
19
- $this.find('.uploader-data-wrapper').append(resp.html)
20
- fileRemoved: (button, item) ->
21
- $(button).closest('.uploader-preview').remove()
22
- fileUpdated: (resp) ->
23
- $this.find('div.uploader-preview[data-asset-id="' + resp.id + '"]').replaceWith(resp.html)
16
+ fileRemoved: (item, button) ->
17
+ $(button).parentsUntil('.uploader-preview').parent().find('.assetable-gallery-item-remove').val('1')
18
+ $(button).parentsUntil('.uploader-preview').parent().fadeOut()
19
+
24
20
 
25
21
  # Make the gallery sortable
26
22
  $(this).sortable
@@ -28,10 +24,16 @@ bind_galleries = ->
28
24
  distance: 50
29
25
  tolerance: 'pointer'
30
26
  placeholder: 'uploader-sortable-placeholder'
27
+ update: (event, ui) ->
28
+ $gallery = $(this)
29
+
30
+ $('input.assetable-gallery-item-sort-order', $gallery).each (index) ->
31
+ $(this).val(index)
31
32
 
32
33
 
33
34
  window.Assetable.bind_galleries = bind_galleries
34
35
 
36
+
35
37
  $(document).ready ->
36
38
 
37
39
  window.Assetable.bind_galleries()
@@ -1,14 +1,30 @@
1
- #= require_self
1
+ bind_uploaders = ->
2
2
 
3
- #= require moxie
4
- #= require plupload.dev
5
- #= require plupload.settings
6
- #= require jquery.plupload.queue
7
- #= require vendor/jquery-ui-1.10.3.custom
8
- #= require vendor/bootstrap-modal
3
+ $('.assetable-uploader').each ->
4
+ unless $(this).hasClass("uploadable")
5
+ $(this).addClass "uploadable"
6
+ $this = $(this)
7
+ $this.removeClass "assetable-uploader"
9
8
 
10
- #= require assetable/assetable_uploader
11
- #= require assetable/gallery
12
- #= require assetable/asset_gallery
9
+ $this.assetable_uploader
10
+ multi_selection: false
11
+ url: "/assetable/assets.js"
12
+ # directions: $this.attr('data-uploader-directions')
13
+ # max_file_size: $this.attr("data-max-file-size")
14
+ authenticity_token: $("meta[name=\"csrf-token\"]").attr("content")
15
+ fileRemoved: (item, button) ->
16
+ # Remove the asset preview and input when removed. No need
17
+ # to add an empty input as one already exists in the DOM
18
+ $('.uploader-preview', item).html('')
13
19
 
14
- window.Assetable = {}
20
+
21
+ window.Assetable.bind_uploaders = bind_uploaders
22
+
23
+ $(document).ready ->
24
+
25
+ window.Assetable.bind_uploaders()
26
+
27
+ # Remove assetable modals on close
28
+ $(document).on "hidden.bs.modal", ".assetable-modal", ->
29
+ $(this).remove()
30
+ return
@@ -1,7 +1,7 @@
1
- /*! jQuery UI - v1.10.3 - 2013-12-03
1
+ /*! jQuery UI - v1.10.4 - 2014-02-17
2
2
  * http://jqueryui.com
3
- * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js
4
- * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
3
+ * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.selectable.js, jquery.ui.sortable.js
4
+ * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
5
 
6
6
  (function( $, undefined ) {
7
7
 
@@ -12,7 +12,7 @@ var uuid = 0,
12
12
  $.ui = $.ui || {};
13
13
 
14
14
  $.extend( $.ui, {
15
- version: "1.10.3",
15
+ version: "1.10.4",
16
16
 
17
17
  keyCode: {
18
18
  BACKSPACE: 8,
@@ -411,7 +411,7 @@ $.widget = function( name, base, prototype ) {
411
411
  // TODO: remove support for widgetEventPrefix
412
412
  // always use the name + a colon as the prefix, e.g., draggable:start
413
413
  // don't prefix for widgets that aren't DOM-based
414
- widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
414
+ widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
415
415
  }, proxiedPrototype, {
416
416
  constructor: constructor,
417
417
  namespace: namespace,
@@ -620,12 +620,12 @@ $.Widget.prototype = {
620
620
  curOption = curOption[ parts[ i ] ];
621
621
  }
622
622
  key = parts.pop();
623
- if ( value === undefined ) {
623
+ if ( arguments.length === 1 ) {
624
624
  return curOption[ key ] === undefined ? null : curOption[ key ];
625
625
  }
626
626
  curOption[ key ] = value;
627
627
  } else {
628
- if ( value === undefined ) {
628
+ if ( arguments.length === 1 ) {
629
629
  return this.options[ key ] === undefined ? null : this.options[ key ];
630
630
  }
631
631
  options[ key ] = value;
@@ -832,7 +832,7 @@ $( document ).mouseup( function() {
832
832
  });
833
833
 
834
834
  $.widget("ui.mouse", {
835
- version: "1.10.3",
835
+ version: "1.10.4",
836
836
  options: {
837
837
  cancel: "input,textarea,button,select,option",
838
838
  distance: 1,
@@ -982,7 +982,267 @@ $.widget("ui.mouse", {
982
982
  })(jQuery);
983
983
  (function( $, undefined ) {
984
984
 
985
- /*jshint loopfunc: true */
985
+ $.widget("ui.selectable", $.ui.mouse, {
986
+ version: "1.10.4",
987
+ options: {
988
+ appendTo: "body",
989
+ autoRefresh: true,
990
+ distance: 0,
991
+ filter: "*",
992
+ tolerance: "touch",
993
+
994
+ // callbacks
995
+ selected: null,
996
+ selecting: null,
997
+ start: null,
998
+ stop: null,
999
+ unselected: null,
1000
+ unselecting: null
1001
+ },
1002
+ _create: function() {
1003
+ var selectees,
1004
+ that = this;
1005
+
1006
+ this.element.addClass("ui-selectable");
1007
+
1008
+ this.dragged = false;
1009
+
1010
+ // cache selectee children based on filter
1011
+ this.refresh = function() {
1012
+ selectees = $(that.options.filter, that.element[0]);
1013
+ selectees.addClass("ui-selectee");
1014
+ selectees.each(function() {
1015
+ var $this = $(this),
1016
+ pos = $this.offset();
1017
+ $.data(this, "selectable-item", {
1018
+ element: this,
1019
+ $element: $this,
1020
+ left: pos.left,
1021
+ top: pos.top,
1022
+ right: pos.left + $this.outerWidth(),
1023
+ bottom: pos.top + $this.outerHeight(),
1024
+ startselected: false,
1025
+ selected: $this.hasClass("ui-selected"),
1026
+ selecting: $this.hasClass("ui-selecting"),
1027
+ unselecting: $this.hasClass("ui-unselecting")
1028
+ });
1029
+ });
1030
+ };
1031
+ this.refresh();
1032
+
1033
+ this.selectees = selectees.addClass("ui-selectee");
1034
+
1035
+ this._mouseInit();
1036
+
1037
+ this.helper = $("<div class='ui-selectable-helper'></div>");
1038
+ },
1039
+
1040
+ _destroy: function() {
1041
+ this.selectees
1042
+ .removeClass("ui-selectee")
1043
+ .removeData("selectable-item");
1044
+ this.element
1045
+ .removeClass("ui-selectable ui-selectable-disabled");
1046
+ this._mouseDestroy();
1047
+ },
1048
+
1049
+ _mouseStart: function(event) {
1050
+ var that = this,
1051
+ options = this.options;
1052
+
1053
+ this.opos = [event.pageX, event.pageY];
1054
+
1055
+ if (this.options.disabled) {
1056
+ return;
1057
+ }
1058
+
1059
+ this.selectees = $(options.filter, this.element[0]);
1060
+
1061
+ this._trigger("start", event);
1062
+
1063
+ $(options.appendTo).append(this.helper);
1064
+ // position helper (lasso)
1065
+ this.helper.css({
1066
+ "left": event.pageX,
1067
+ "top": event.pageY,
1068
+ "width": 0,
1069
+ "height": 0
1070
+ });
1071
+
1072
+ if (options.autoRefresh) {
1073
+ this.refresh();
1074
+ }
1075
+
1076
+ this.selectees.filter(".ui-selected").each(function() {
1077
+ var selectee = $.data(this, "selectable-item");
1078
+ selectee.startselected = true;
1079
+ if (!event.metaKey && !event.ctrlKey) {
1080
+ selectee.$element.removeClass("ui-selected");
1081
+ selectee.selected = false;
1082
+ selectee.$element.addClass("ui-unselecting");
1083
+ selectee.unselecting = true;
1084
+ // selectable UNSELECTING callback
1085
+ that._trigger("unselecting", event, {
1086
+ unselecting: selectee.element
1087
+ });
1088
+ }
1089
+ });
1090
+
1091
+ $(event.target).parents().addBack().each(function() {
1092
+ var doSelect,
1093
+ selectee = $.data(this, "selectable-item");
1094
+ if (selectee) {
1095
+ doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
1096
+ selectee.$element
1097
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
1098
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
1099
+ selectee.unselecting = !doSelect;
1100
+ selectee.selecting = doSelect;
1101
+ selectee.selected = doSelect;
1102
+ // selectable (UN)SELECTING callback
1103
+ if (doSelect) {
1104
+ that._trigger("selecting", event, {
1105
+ selecting: selectee.element
1106
+ });
1107
+ } else {
1108
+ that._trigger("unselecting", event, {
1109
+ unselecting: selectee.element
1110
+ });
1111
+ }
1112
+ return false;
1113
+ }
1114
+ });
1115
+
1116
+ },
1117
+
1118
+ _mouseDrag: function(event) {
1119
+
1120
+ this.dragged = true;
1121
+
1122
+ if (this.options.disabled) {
1123
+ return;
1124
+ }
1125
+
1126
+ var tmp,
1127
+ that = this,
1128
+ options = this.options,
1129
+ x1 = this.opos[0],
1130
+ y1 = this.opos[1],
1131
+ x2 = event.pageX,
1132
+ y2 = event.pageY;
1133
+
1134
+ if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
1135
+ if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
1136
+ this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
1137
+
1138
+ this.selectees.each(function() {
1139
+ var selectee = $.data(this, "selectable-item"),
1140
+ hit = false;
1141
+
1142
+ //prevent helper from being selected if appendTo: selectable
1143
+ if (!selectee || selectee.element === that.element[0]) {
1144
+ return;
1145
+ }
1146
+
1147
+ if (options.tolerance === "touch") {
1148
+ hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
1149
+ } else if (options.tolerance === "fit") {
1150
+ hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
1151
+ }
1152
+
1153
+ if (hit) {
1154
+ // SELECT
1155
+ if (selectee.selected) {
1156
+ selectee.$element.removeClass("ui-selected");
1157
+ selectee.selected = false;
1158
+ }
1159
+ if (selectee.unselecting) {
1160
+ selectee.$element.removeClass("ui-unselecting");
1161
+ selectee.unselecting = false;
1162
+ }
1163
+ if (!selectee.selecting) {
1164
+ selectee.$element.addClass("ui-selecting");
1165
+ selectee.selecting = true;
1166
+ // selectable SELECTING callback
1167
+ that._trigger("selecting", event, {
1168
+ selecting: selectee.element
1169
+ });
1170
+ }
1171
+ } else {
1172
+ // UNSELECT
1173
+ if (selectee.selecting) {
1174
+ if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
1175
+ selectee.$element.removeClass("ui-selecting");
1176
+ selectee.selecting = false;
1177
+ selectee.$element.addClass("ui-selected");
1178
+ selectee.selected = true;
1179
+ } else {
1180
+ selectee.$element.removeClass("ui-selecting");
1181
+ selectee.selecting = false;
1182
+ if (selectee.startselected) {
1183
+ selectee.$element.addClass("ui-unselecting");
1184
+ selectee.unselecting = true;
1185
+ }
1186
+ // selectable UNSELECTING callback
1187
+ that._trigger("unselecting", event, {
1188
+ unselecting: selectee.element
1189
+ });
1190
+ }
1191
+ }
1192
+ if (selectee.selected) {
1193
+ if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
1194
+ selectee.$element.removeClass("ui-selected");
1195
+ selectee.selected = false;
1196
+
1197
+ selectee.$element.addClass("ui-unselecting");
1198
+ selectee.unselecting = true;
1199
+ // selectable UNSELECTING callback
1200
+ that._trigger("unselecting", event, {
1201
+ unselecting: selectee.element
1202
+ });
1203
+ }
1204
+ }
1205
+ }
1206
+ });
1207
+
1208
+ return false;
1209
+ },
1210
+
1211
+ _mouseStop: function(event) {
1212
+ var that = this;
1213
+
1214
+ this.dragged = false;
1215
+
1216
+ $(".ui-unselecting", this.element[0]).each(function() {
1217
+ var selectee = $.data(this, "selectable-item");
1218
+ selectee.$element.removeClass("ui-unselecting");
1219
+ selectee.unselecting = false;
1220
+ selectee.startselected = false;
1221
+ that._trigger("unselected", event, {
1222
+ unselected: selectee.element
1223
+ });
1224
+ });
1225
+ $(".ui-selecting", this.element[0]).each(function() {
1226
+ var selectee = $.data(this, "selectable-item");
1227
+ selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
1228
+ selectee.selecting = false;
1229
+ selectee.selected = true;
1230
+ selectee.startselected = true;
1231
+ that._trigger("selected", event, {
1232
+ selected: selectee.element
1233
+ });
1234
+ });
1235
+ this._trigger("stop", event);
1236
+
1237
+ this.helper.remove();
1238
+
1239
+ return false;
1240
+ }
1241
+
1242
+ });
1243
+
1244
+ })(jQuery);
1245
+ (function( $, undefined ) {
986
1246
 
987
1247
  function isOverAxis( x, reference, size ) {
988
1248
  return ( x > reference ) && ( x < ( reference + size ) );
@@ -993,7 +1253,7 @@ function isFloating(item) {
993
1253
  }
994
1254
 
995
1255
  $.widget("ui.sortable", $.ui.mouse, {
996
- version: "1.10.3",
1256
+ version: "1.10.4",
997
1257
  widgetEventPrefix: "sort",
998
1258
  ready: false,
999
1259
  options: {
@@ -1334,12 +1594,12 @@ $.widget("ui.sortable", $.ui.mouse, {
1334
1594
  }
1335
1595
 
1336
1596
  // Only put the placeholder inside the current Container, skip all
1337
- // items form other containers. This works because when moving
1597
+ // items from other containers. This works because when moving
1338
1598
  // an item from one container to another the
1339
1599
  // currentContainer is switched before the placeholder is moved.
1340
1600
  //
1341
- // Without this moving items in "sub-sortables" can cause the placeholder to jitter
1342
- // beetween the outer and inner container.
1601
+ // Without this, moving items in "sub-sortables" can cause
1602
+ // the placeholder to jitter beetween the outer and inner container.
1343
1603
  if (item.instance !== this.currentContainer) {
1344
1604
  continue;
1345
1605
  }
@@ -1607,10 +1867,11 @@ $.widget("ui.sortable", $.ui.mouse, {
1607
1867
 
1608
1868
  queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
1609
1869
 
1870
+ function addItems() {
1871
+ items.push( this );
1872
+ }
1610
1873
  for (i = queries.length - 1; i >= 0; i--){
1611
- queries[i][0].each(function() {
1612
- items.push(this);
1613
- });
1874
+ queries[i][0].each( addItems );
1614
1875
  }
1615
1876
 
1616
1877
  return $(items);
@@ -2168,12 +2429,17 @@ $.widget("ui.sortable", $.ui.mouse, {
2168
2429
 
2169
2430
 
2170
2431
  //Post events to containers
2432
+ function delayEvent( type, instance, container ) {
2433
+ return function( event ) {
2434
+ container._trigger( type, event, instance._uiHash( instance ) );
2435
+ };
2436
+ }
2171
2437
  for (i = this.containers.length - 1; i >= 0; i--){
2172
- if(!noPropagation) {
2173
- delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2438
+ if (!noPropagation) {
2439
+ delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
2174
2440
  }
2175
2441
  if(this.containers[i].containerCache.over) {
2176
- delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2442
+ delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
2177
2443
  this.containers[i].containerCache.over = 0;
2178
2444
  }
2179
2445
  }