radiant-clipped-extension 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +230 -0
  3. data/Rakefile +109 -0
  4. data/app/controllers/admin/assets_controller.rb +60 -0
  5. data/app/controllers/admin/page_attachments_controller.rb +18 -0
  6. data/app/helpers/admin/assets_helper.rb +16 -0
  7. data/app/models/asset.rb +224 -0
  8. data/app/models/asset_tags.rb +384 -0
  9. data/app/models/asset_type.rb +170 -0
  10. data/app/models/old_page_attachment.rb +26 -0
  11. data/app/models/page_attachment.rb +21 -0
  12. data/app/views/admin/assets/_asset.html.haml +12 -0
  13. data/app/views/admin/assets/_asset_table.html.haml +30 -0
  14. data/app/views/admin/assets/_errors.html.haml +3 -0
  15. data/app/views/admin/assets/_form.html.haml +20 -0
  16. data/app/views/admin/assets/_page_assets.html.haml +12 -0
  17. data/app/views/admin/assets/_search.html.haml +17 -0
  18. data/app/views/admin/assets/_search_results.html.haml +17 -0
  19. data/app/views/admin/assets/edit.html.haml +40 -0
  20. data/app/views/admin/assets/index.html.haml +19 -0
  21. data/app/views/admin/assets/new.html.haml +24 -0
  22. data/app/views/admin/assets/refresh.html.haml +14 -0
  23. data/app/views/admin/assets/remove.html.haml +16 -0
  24. data/app/views/admin/configuration/_edit.html.haml +8 -0
  25. data/app/views/admin/configuration/_show.html.haml +12 -0
  26. data/app/views/admin/page_attachments/_attachment.html.haml +25 -0
  27. data/app/views/admin/page_parts/_page_part.html.haml +21 -0
  28. data/app/views/admin/pages/_asset_popups.html.haml +42 -0
  29. data/app/views/admin/pages/_assets.html.haml +11 -0
  30. data/app/views/admin/removed/_assets_bucket.html.haml +8 -0
  31. data/app/views/admin/removed/_assets_container.html.haml +58 -0
  32. data/app/views/admin/removed/_bucket.html.haml +11 -0
  33. data/app/views/admin/removed/_bucket_asset.html.haml +9 -0
  34. data/app/views/admin/removed/_show_bucket_link.html.haml +4 -0
  35. data/app/views/admin/removed/_upload_to_page.html.haml +12 -0
  36. data/app/views/admin/removed/bucket/_iframe.html.haml +1 -0
  37. data/artwork/icons.png +0 -0
  38. data/clipped_extension.rb +89 -0
  39. data/config/initializers/interpolation.rb +6 -0
  40. data/config/initializers/processors.rb +43 -0
  41. data/config/initializers/radiant_config.rb +34 -0
  42. data/config/locales/en.yml +108 -0
  43. data/config/locales/nl.yml +105 -0
  44. data/config/routes.rb +8 -0
  45. data/cucumber.yml +1 -0
  46. data/db/migrate/001_create_assets.rb +12 -0
  47. data/db/migrate/002_create_paperclip_attributes.rb +13 -0
  48. data/db/migrate/003_create_user_observer.rb +13 -0
  49. data/db/migrate/004_create_page_attachments.rb +19 -0
  50. data/db/migrate/005_rename_users.rb +13 -0
  51. data/db/migrate/20090316132151_disable_file_types.rb +20 -0
  52. data/db/migrate/20110513205050_asset_uuid.rb +11 -0
  53. data/db/migrate/20110606111250_update_configuration.rb +28 -0
  54. data/db/migrate/20110609101438_dimensions.rb +13 -0
  55. data/features/support/env.rb +11 -0
  56. data/features/support/paths.rb +22 -0
  57. data/lib/clipped_admin_ui.rb +32 -0
  58. data/lib/page_asset_associations.rb +13 -0
  59. data/lib/paperclip/frame_grab.rb +73 -0
  60. data/lib/paperclip/geometry_transformation.rb +79 -0
  61. data/lib/radiant-clipped-extension.rb +2 -0
  62. data/lib/radiant-clipped-extension/version.rb +3 -0
  63. data/lib/tasks/clipped_extension_tasks.rake +126 -0
  64. data/lib/tasks/paperclip_tasks.rake +79 -0
  65. data/public/flash/ZeroClipboard.swf +0 -0
  66. data/public/images/admin/assets/add.png +0 -0
  67. data/public/images/admin/assets/archive_icon.png +0 -0
  68. data/public/images/admin/assets/audio_icon.png +0 -0
  69. data/public/images/admin/assets/audio_thumbnail.png +0 -0
  70. data/public/images/admin/assets/c_icon.png +0 -0
  71. data/public/images/admin/assets/copy.png +0 -0
  72. data/public/images/admin/assets/css_icon.png +0 -0
  73. data/public/images/admin/assets/database_icon.png +0 -0
  74. data/public/images/admin/assets/delete.png +0 -0
  75. data/public/images/admin/assets/document_icon.png +0 -0
  76. data/public/images/admin/assets/document_thumbnail.png +0 -0
  77. data/public/images/admin/assets/flash_icon.png +0 -0
  78. data/public/images/admin/assets/flash_thumbnail.png +0 -0
  79. data/public/images/admin/assets/font_icon.png +0 -0
  80. data/public/images/admin/assets/gzip_icon.png +0 -0
  81. data/public/images/admin/assets/html_icon.png +0 -0
  82. data/public/images/admin/assets/image_icon.png +0 -0
  83. data/public/images/admin/assets/image_thumbnail.png +0 -0
  84. data/public/images/admin/assets/java_icon.png +0 -0
  85. data/public/images/admin/assets/page_edit.png +0 -0
  86. data/public/images/admin/assets/perl_icon.png +0 -0
  87. data/public/images/admin/assets/php_icon.png +0 -0
  88. data/public/images/admin/assets/presentation_icon.png +0 -0
  89. data/public/images/admin/assets/python_icon.png +0 -0
  90. data/public/images/admin/assets/reorder_assets.png +0 -0
  91. data/public/images/admin/assets/ruby_icon.png +0 -0
  92. data/public/images/admin/assets/script_icon.png +0 -0
  93. data/public/images/admin/assets/spreadsheet_icon.png +0 -0
  94. data/public/images/admin/assets/tar_icon.png +0 -0
  95. data/public/images/admin/assets/unknown_icon.png +0 -0
  96. data/public/images/admin/assets/unknown_thumbnail.png +0 -0
  97. data/public/images/admin/assets/video_icon.png +0 -0
  98. data/public/images/admin/assets/video_thumbnail.png +0 -0
  99. data/public/images/admin/assets/xml_icon.png +0 -0
  100. data/public/images/admin/assets/zip_icon.png +0 -0
  101. data/public/javascripts/admin/assets.js +296 -0
  102. data/public/stylesheets/sass/admin/assets.sass +209 -0
  103. data/radiant-clipped-extension.gemspec +33 -0
  104. data/spec/controllers/admin/assets_controller_spec.rb +50 -0
  105. data/spec/controllers/admin/page_attachments_controller_spec.rb +50 -0
  106. data/spec/datasets/assets_dataset.rb +35 -0
  107. data/spec/fixtures/test.flv +0 -0
  108. data/spec/lib/asset_tags_spec.rb +101 -0
  109. data/spec/lib/frame_grab_spec.rb +17 -0
  110. data/spec/lib/geometry_transformation_spec.rb +63 -0
  111. data/spec/models/asset_spec.rb +72 -0
  112. data/spec/models/asset_type_spec.rb +63 -0
  113. data/spec/spec.opts +6 -0
  114. data/spec/spec_helper.rb +36 -0
  115. data/wireframes/edit-page-assets-2.bmml +453 -0
  116. data/wireframes/edit-page-assets-2.png +0 -0
  117. data/wireframes/edit-page-assets-3.bmml +454 -0
  118. data/wireframes/edit-page-assets-3.png +0 -0
  119. data/wireframes/edit-page-assets.bmml +433 -0
  120. data/wireframes/edit-page-assets.png +0 -0
  121. data/wireframes/edit-page.bmml +174 -0
  122. data/wireframes/edit-page.png +0 -0
  123. metadata +249 -0
@@ -0,0 +1,296 @@
1
+ var Asset = {};
2
+
3
+ Asset.Upload = Behavior.create({
4
+ onsubmit: function (e) {
5
+ if (e) e.stop();
6
+ var uuid = Asset.GenerateUUID();
7
+ var ulframe = document.createElement('iframe');
8
+ ulframe.setAttribute('name', uuid); // this doesn't work on ie7: will need bodging
9
+ $('upload_holders').insert(ulframe);
10
+
11
+ var form = this.element;
12
+ var title = form.down('input.textbox').value || form.down('input.file').value;
13
+ var placeholder = Asset.AddPlaceholder(title);
14
+
15
+ form.setAttribute('target', uuid);
16
+ ulframe.observe('load', function (e) {
17
+ if (e) e.stop();
18
+ var response = ulframe.contentDocument.body.innerHTML;
19
+ if (response && response != "") {
20
+ placeholder.remove();
21
+ Asset.AddToList(response);
22
+ ulframe.remove();
23
+ }
24
+ });
25
+
26
+ form.submit();
27
+ $('upload_asset').closePopup();
28
+
29
+ // Small delay is required here to let safari assemble the payload
30
+ // form.down('input').clear().defer();
31
+ // form.down('input.file').clear().defer();
32
+ }
33
+ });
34
+
35
+
36
+ // this local attachment method works and is much quicker, but it's fragile and doesn't notice radiant configuration changes
37
+ // better to bounce off the server, provided it can be made responsive enough.
38
+
39
+ // Asset.Attach = Behavior.create({
40
+ // onclick: function (e) {
41
+ // if (e) e.stop();
42
+ // var container = this.element.up('li.asset');
43
+ // container.addClassName('waiting');
44
+ // var title = container.down('div.title').innerHTML;
45
+ // var image = container.down('img');
46
+ // var uuid = Asset.GenerateUUID();
47
+ // var asset_id = this.element.getAttribute('rel').split('_').last();
48
+ // var attachment_field = document.createElement('input');
49
+ // attachment_field.setAttribute('type', 'hidden');
50
+ // attachment_field.setAttribute('id', 'page_page_attachments_attributes_' + uuid + '_asset_id');
51
+ // attachment_field.setAttribute('name', 'page[page_attachments_attributes][' + uuid + '][asset_id]');
52
+ // attachment_field.value = asset_id;
53
+ // var placeholder = Asset.AddPlaceholder(title, image, attachment_field);
54
+ // container.removeClassName('waiting');
55
+ // placeholder.removeClassName('waiting');
56
+ // }
57
+ // });
58
+
59
+ // ajax-based page attachment is a slightly slower but probably more robust option
60
+ //
61
+ Asset.Attach = Behavior.create({
62
+ onclick: function (e) {
63
+ if (e) e.stop();
64
+ var container = this.element.up('li.asset');
65
+ var title = container.down('div.title').innerHTML;
66
+ var image = container.down('img');
67
+ var placeholder = Asset.AddPlaceholder(title, image);
68
+ container.addClassName('waiting');
69
+ new Ajax.Request(this.element.href, {
70
+ asynchronous: true,
71
+ evalScripts: false,
72
+ method: 'get',
73
+ onSuccess: function(transport) {
74
+ container.removeClassName('waiting');
75
+ placeholder.remove();
76
+ Asset.AddToList(transport.responseText);
77
+ }
78
+ });
79
+ }
80
+ });
81
+
82
+ Asset.Detach = Behavior.create({
83
+ onclick: function (e) {
84
+ if (e) e.stop();
85
+ Asset.RemoveFromList(this.element.up('li.asset'));
86
+ }
87
+ });
88
+
89
+ Asset.Insert = Behavior.create({
90
+ onclick: function(e) {
91
+ if (e) e.stop();
92
+ var part_name = TabControlBehavior.instances[0].controller.selected.caption;
93
+ var textbox = $('part_' + part_name + '_content');
94
+ var tag_parts = this.element.getAttribute('rel').split('_');
95
+ var tag_name = tag_parts[0];
96
+ var asset_size = tag_parts[1];
97
+ var asset_id = tag_parts[2];
98
+ var radius_tag = '<r:asset:' + tag_name;
99
+ if (asset_size != '') radius_tag = radius_tag + ' size="' + asset_size + '"';
100
+ radius_tag = radius_tag +' id="' + asset_id + '" />';
101
+ Asset.InsertAtCursor(textbox, radius_tag);
102
+ }
103
+ });
104
+
105
+ Asset.Sortable = Behavior.create({
106
+ initialize: function (e) {
107
+ this.sorter = Asset.MakeSortable(this.element);
108
+ }
109
+ });
110
+
111
+ // Asset-filter and search functions are available wherever the asset_table partial is displayed
112
+
113
+ Asset.DeselectFileTypes = Behavior.create({
114
+ onclick: function(e){
115
+ e.stop();
116
+ var element = this.element;
117
+ if(!element.hasClassName('pressed')) {
118
+ $$('a.selective').each(function(el) { el.removeClassName('pressed'); });
119
+ $$('input.selective').each(function(el) { el.removeAttribute('checked'); });
120
+ element.addClassName('pressed');
121
+ Asset.UpdateTable(true);
122
+ }
123
+ }
124
+ });
125
+
126
+ Asset.SelectFileType = Behavior.create({
127
+ onclick: function(e){
128
+ e.stop();
129
+ var element = this.element;
130
+ var type_id = element.readAttribute("rel");
131
+ var type_check = $(type_id + '-check');
132
+ if(element.hasClassName('pressed')) {
133
+ element.removeClassName('pressed');
134
+ type_check.removeAttribute('checked');
135
+ if ($$('a.selective.pressed').length == 0) $('select_all').addClassName('pressed');
136
+ } else {
137
+ element.addClassName('pressed');
138
+ $$('a.deselective').each(function(el) { el.removeClassName('pressed'); });
139
+ type_check.setAttribute('checked', 'checked');
140
+ }
141
+ Asset.UpdateTable(true);
142
+ }
143
+ });
144
+
145
+ Asset.SearchForm = Behavior.create({
146
+ initialize: function () {
147
+ this.observer = new Form.Element.Observer(this.element.down('input.search'), 2, Asset.UpdateTable);
148
+ },
149
+ onsubmit: function (e) {
150
+ if (e) e.stop();
151
+ Asset.UpdateTable(true);
152
+ }
153
+ });
154
+
155
+ Asset.Pagination = Behavior.create({
156
+ onclick: function (e) {
157
+ if (e) e.stop();
158
+ var url = this.element.readAttribute('href');
159
+ var pagination = url.toQueryParams();
160
+ var search_form = $('filesearchform');
161
+ search_form.down('#p').value = pagination['p'];
162
+ Asset.UpdateTable(false);
163
+ }
164
+ });
165
+
166
+ Asset.MakeSortable = function (element) {
167
+ var sorter = Sortable.create(element, {
168
+ overlap: 'horizontal',
169
+ constraint: false,
170
+ handle: 'title',
171
+ onChange: function (e) {
172
+ Asset.SetPositions();
173
+ Asset.Notify('Assets reordered. Save page to commit changes.');
174
+ }
175
+ });
176
+ element.addClassName('sortable');
177
+ Asset.SetPositions();
178
+ return sorter;
179
+ }
180
+
181
+ Asset.SetPositions = function () {
182
+ $('attachment_fields').select('input.pos').each(function (input, index) {
183
+ input.value = index;
184
+ });
185
+ }
186
+
187
+ // originally taken from phpMyAdmin
188
+ Asset.InsertAtCursor = function(field, insertion) {
189
+ if (document.selection) { // ie
190
+ field.focus();
191
+ var sel = document.selection.createRange();
192
+ sel.text = insertion;
193
+ }
194
+ else if (field.selectionStart || field.selectionStart == '0') { // moz
195
+ var startPos = field.selectionStart;
196
+ var endPos = field.selectionEnd;
197
+ field.value = field.value.substring(0, startPos) + insertion + field.value.substring(endPos, field.value.length);
198
+ field.selectionStart = field.selectionEnd = startPos + insertion.length;
199
+ } else {
200
+ field.value += value;
201
+ }
202
+ }
203
+
204
+ Asset.GenerateUUID = function () {
205
+ // http://www.ietf.org/rfc/rfc4122.txt
206
+ var s = [];
207
+ var hexDigits = "0123456789ABCDEF";
208
+ for (var i = 0; i < 32; i++) { s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); }
209
+ s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
210
+ s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
211
+ return s.join('');
212
+ };
213
+
214
+ Asset.UpdateTable = function (depaginate) {
215
+ var search_form = $('filesearchform');
216
+ if (depaginate && search_form.down('#p')) search_form.down('#p').value = 1;
217
+ Asset.AllWaiting();
218
+ new Ajax.Updater('assets_table', search_form.action, {
219
+ asynchronous: true,
220
+ evalScripts: false,
221
+ parameters: Form.serialize(search_form),
222
+ method: 'get'
223
+ });
224
+ }
225
+
226
+ Asset.AddToList = function (html) {
227
+ var list = $('attachment_fields');
228
+ list.insert(html);
229
+ Asset.ShowListIfHidden();
230
+ Asset.Notify('Save page to commit changes');
231
+ Event.addBehavior.reload(); // #TODO something a bit more specific would be nice here
232
+ Asset.MakeSortable(list);
233
+ }
234
+
235
+ Asset.RemoveFromList = function (container) {
236
+ var el = null;
237
+ if (!!(el = container.down('input.attacher'))) el.remove();
238
+ if (!!(el = container.down('input.pos'))) el.remove();
239
+ if (!!(el = container.down('input.destroyer'))) el.value = 1;
240
+ container.dropOut({afterFinish: Asset.HideListIfEmpty});
241
+ container.addClassName('detached');
242
+ }
243
+
244
+ Asset.AddPlaceholder = function (title, image, contents) {
245
+ var placeholder = document.createElement('li').addClassName('asset').addClassName('waiting');
246
+ if (contents) placeholder.insert(contents);
247
+ var front = document.createElement('div').addClassName('front');
248
+ if (image) front.insert(document.createElement('div').addClassName('thumbnail').insert(image.clone()));
249
+ placeholder.insert(front);
250
+ if (!title) title = 'please wait';
251
+ var back = document.createElement('div').addClassName('back').insert(document.createElement('div').addClassName('title').update(title));
252
+ placeholder.insert(back);
253
+ $('attachment_fields').insert(placeholder);
254
+ Asset.ShowListIfHidden();
255
+ return placeholder;
256
+ }
257
+
258
+ Asset.AllWaiting = function (container) {
259
+ if (!container) container = $('assets_table');
260
+ container.select('li.asset').each(function (el) { el.addClassName('waiting'); });
261
+ }
262
+
263
+ Asset.Notify = function (message) {
264
+ $('attachment_list').down('span.message').update(message).addClassName('important');
265
+ }
266
+
267
+ Asset.ShowListIfHidden = function () {
268
+ var list = $('attachment_fields');
269
+ if (list.hasClassName('empty')) {
270
+ list.removeClassName('empty');
271
+ // list.slideDown();
272
+ }
273
+ }
274
+
275
+ Asset.HideListIfEmpty = function () {
276
+ var list = $('attachment_fields');
277
+ if (!list.down('li.asset:not(.detached)')) {
278
+ list.addClassName('empty');
279
+ // list.slideUp();
280
+ Asset.Notify('All assets detached. Save page to commit changes');
281
+ } else {
282
+ Asset.Notify('Assets detached. Save page to commit changes');
283
+ }
284
+ }
285
+
286
+ Event.addBehavior({
287
+ 'ul#attachment_fields': Asset.Sortable,
288
+ 'form.upload_asset': Asset.Upload,
289
+ 'a.attach_asset': Asset.Attach,
290
+ 'a.detach_asset': Asset.Detach,
291
+ 'a.insert_asset': Asset.Insert,
292
+ 'a.deselective': Asset.DeselectFileTypes,
293
+ 'a.selective': Asset.SelectFileType,
294
+ 'form.search': Asset.SearchForm,
295
+ '#assets_table .pagination a': Asset.Pagination
296
+ });
@@ -0,0 +1,209 @@
1
+ @import "base"
2
+
3
+ p.asset
4
+ img.preview
5
+ border: 5px solid white
6
+ +box-shadow
7
+
8
+ .asset_filters
9
+ float: left
10
+ padding: 2px 0
11
+ a
12
+ +border-radius(100px)
13
+ color: #555
14
+ padding: 3px 8px
15
+ text-decoration: none
16
+ font-size: 12px
17
+ &:hover
18
+ background: #ccc
19
+ &.pressed
20
+ background: #888
21
+ +box-shadow(0, 1px, 1px, #333, inset)
22
+ color: white
23
+ text-shadow: 0 1px 0 #333
24
+ &:hover
25
+ background: #888
26
+ +box-shadow(0, 1px, 1px, #333, inset)
27
+ color: white
28
+ text-shadow: 0 1px 0 #333
29
+
30
+ .popup
31
+ div.toolbar
32
+ background: white
33
+ +linear-gradient(color-stops(white, #ddd))
34
+ border-bottom: 1px solid #ccc
35
+ +box-shadow(white, 0, 1px, 0)
36
+ margin: -20px -20px 0
37
+ padding: 6px 10px 3px 10px
38
+ font-size: 95%
39
+ height: 30px
40
+ +clearfix
41
+ .right
42
+ float: right
43
+ form.search
44
+ padding: 4px 2px 0
45
+ input[type=search]
46
+ font-size: 12px
47
+ +border-radius(100px)
48
+ border: 1px solid #ccc
49
+ border-top-color: #999
50
+ border-left-color: #b0b0b0
51
+ border-right-color: #bbb
52
+ background: white image_url('admin/search.png') 4px center no-repeat
53
+ +box-shadow(rgba(black, 0.2), 0, 1px, 0, inset)
54
+ width: 180px
55
+ padding: 2px 8px 2px 20px
56
+
57
+ #upload_holders
58
+ display: none
59
+
60
+ #attach_asset
61
+ .viewport
62
+ overflow-x: hidden
63
+ width: 610px
64
+ height: 310px
65
+
66
+ .attachment_actions
67
+ text-align: right
68
+ margin-bottom: -1em
69
+ ul
70
+ +inline-list
71
+ li
72
+ padding-left: 1em
73
+ a
74
+ color: white !important
75
+ text-shadow: 1px 1px 0 #888
76
+
77
+ .assets
78
+ padding-left: 5px
79
+ padding-right: 5px
80
+ ul
81
+ li.asset
82
+ display: block
83
+ float: left
84
+ margin: 8px 0 0 8px
85
+ width: 110px
86
+ height: 110px
87
+ position: relative
88
+ line-height: 1.2em
89
+ .front, .back
90
+ display: block
91
+ background: #e6eaed
92
+ border: 5px solid white
93
+ position: absolute
94
+ width: 100px
95
+ height: 100px
96
+ text-align: center
97
+ .front
98
+ +box-shadow
99
+ text-align: center
100
+ .back
101
+ color: #333
102
+ overflow: hidden
103
+ +opacity(0)
104
+ .title
105
+ color: #333
106
+ font-size: 10px
107
+ overflow: hidden
108
+ margin: 10px 4px
109
+ height: 15px
110
+ line-height: 15px
111
+ text-overflow: ellipsis
112
+ .icon
113
+ height: 63px
114
+ line-height: 63px
115
+ img
116
+ vertical-align: bottom
117
+ ul.actions
118
+ li
119
+ margin: 5px 0
120
+ padding: 0 10px
121
+ font-size: 10px
122
+ a
123
+ background: #666
124
+ background: rgba(black, 0.8)
125
+ +border-radius
126
+ color: #ddd
127
+ display: block
128
+ padding: 2px 10px
129
+ text-decoration: none
130
+ &:hover
131
+ background: #999
132
+ background: rgba(black, 0.6)
133
+ color: white
134
+ &.unsaved
135
+ .front
136
+ opacity: 0.4
137
+ &:hover
138
+ .back
139
+ +opacity(1)
140
+ background: rgba(white, 0.6)
141
+ &.waiting
142
+ background-color: #E6EAED
143
+ .back
144
+ display: none
145
+ .front
146
+ background: transparent url(/images/admin/spinner.gif) no-repeat center center
147
+ img
148
+ opacity: 0.2
149
+
150
+ #attachment_list.assets
151
+ background: #7e7e7e
152
+ +border-bottom-radius
153
+ margin: -1em 0.5em 1em 0.5em
154
+ overflow-y: hidden
155
+ overflow-x: auto
156
+ ul.empty
157
+ display: none
158
+ p.note
159
+ font-size: 80%
160
+ margin: 0
161
+ padding: 8px
162
+ clear: left
163
+ span.message
164
+ float: right
165
+ color: #aaa
166
+ &.important
167
+ color: #d99
168
+ ul.sortable
169
+ li.asset
170
+ div.title
171
+ cursor: move
172
+ &:hover
173
+ font-weight: bold
174
+
175
+ #assets_table.assets
176
+ position: relative
177
+ p
178
+ padding: 40px
179
+ top: 45px
180
+ color: silver
181
+ text-align: center
182
+ font:
183
+ size: 75%
184
+ style: oblique
185
+ ul
186
+ clear: both
187
+ li.asset
188
+ input
189
+ display: none
190
+ div.pagination
191
+ position: relative
192
+ clear: left
193
+ width: 100%
194
+ height: 2.3em
195
+ font-size: 80%
196
+ text-align: center
197
+ a
198
+ color: white
199
+ text-decoration: none
200
+ &:hover
201
+ background-color: #bbb
202
+ color: #444
203
+ span
204
+ color: #bbb
205
+ span, a
206
+ display: block
207
+ float: left
208
+ padding: 5px
209
+ line-height: 1.5em