scrivito_content_browser 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cb03fa9aa6c9dc6e81e1656cc5a28f0bd13d5622
4
+ data.tar.gz: f518d7a5522564df0dc67a9a2cc698d371c83959
5
+ SHA512:
6
+ metadata.gz: 882eba0b83ba5ba43d41fe32fff51523ad958cd3cc213024ab712b0595180e1a20af7e6058401e3ede0188a37914ad30b41b5b5d1564fabff1537a3ed4c34cca
7
+ data.tar.gz: f06648ee26ac24f098fddf73bacf90dd82e1b5bf64ecb0fd56c3cd79a954c48e2cb266b05eb8d83e1f28f9619dfe7b988ceac48dc73b9387bfadd6d9e86b0680
data/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # v0.1.0
2
+ * Renamed from Scrivito Resource Browser to Scrivito Content Browser
3
+ * API change: `Resourcebrowser` is now `scrivito.content_browser`
4
+ * API change: `ResourcebrowserUploader.mimeTypeMapping` is now
5
+ `scrivito.content_browser.filter_defaults.upload`
6
+ * API change: option `.open(onSave)` is now a promise: `.open().done`
7
+ * API change: option `.open(onClose)` is now a promise: `.open().fail`
8
+ * API change: removed option `.open(onDelete)`
9
+ * See your app's JS console for hints and deprecation warnings
10
+
11
+ # v0.0.6
12
+ * Added list view mode
13
+ * The _Selected_ filter appears at the top of the filter list
14
+ * Changed the icon namespace to `scrivito-resourcebrowser-icon-*`
15
+ `editing-icon-*` is still supported for the filter option `icon`
16
+ * Dropped unused controller actions, leaving only `inspector`
17
+
18
+ # v0.0.5
19
+ * Uploading a MIME type with no configured `obj_class` shows sensible error message.
20
+ * Show the app configurable `description_for_editor` as subtitle.
21
+ * Some visual improvements.
22
+
23
+ # v0.0.4
24
+ * The filters are now a simple hash instead of a function that returns a hash. This allows to
25
+ extend the filters multiple times. This is useful, when a gem wants to add filters to the ones
26
+ already defined in the application. (Thanks @gertimon)
27
+
28
+ # v0.0.3
29
+ * Change the icon to open the details view from a magnifying glass to a pen.
30
+ * Added option "selectionMode", which can be set to `single` in order to allow only one selected
31
+ item at a time. Any other value will allow to select an arbitrary number of items.
32
+ * Added "selected" filter that displays all currently selected items.
33
+ * Display "missing title" when a custom filter has no title configured.
34
+ * Added installation and usage section in the README.
35
+
36
+ # v0.0.2
37
+ * Bugfix: An error on assets:precompile was caused by a typo. (Thanks @dcsaszar)
38
+
39
+ # v0.0.1
40
+ * rename to resource browser
41
+ * initial version
data/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ Copyright (c) 2009 - 2014 Infopark AG (http://www.infopark.com)
2
+
3
+ This software can be used and modified under the LGPL-3.0. Please refer to
4
+ http://www.gnu.org/licenses/lgpl-3.0.html for the license text.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Scrivito Content Browser
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/scrivito_content_browser.png)](http://badge.fury.io/rb/scrivito_content_browser)
4
+
5
+ The [Scrivito](http://scrivito.com) content browser is a JavaScript based tool to add, update and
6
+ delete Scrivito CMS resources and documents.
7
+ It provides flexible configuration options and can easily be integrated into your application.
8
+
9
+ ## Installation and Usage
10
+
11
+ If you already use the gem [scrivito_editors](https://rubygems.org/gems/scrivito_editors) then you
12
+ don't have to change anything, because it is a dependency that will be installed automatically.
13
+
14
+ If you want to use this gem separately, please add it to your `Gemfile`.
15
+
16
+ gem 'scrivito_content_browser'
17
+
18
+ Then require it in your stylesheet manifest.
19
+
20
+ *= require scrivito_content_browser
21
+
22
+ And require it in your JavaScript manifest.
23
+
24
+ //= require scrivito_content_browser
25
+
26
+
27
+ ## Changelog
28
+
29
+ {include:file:CHANGELOG.md}
30
+
31
+
32
+ ## License
33
+ Copyright (c) 2009 - 2014 Infopark AG (http://www.infopark.com)
34
+
35
+ This software can be used and modified under the LGPL-3.0. Please refer to
36
+ http://www.gnu.org/licenses/lgpl-3.0.html for the license text.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler/setup'
4
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,527 @@
1
+ # Sanity check
2
+ if !scrivito?
3
+ console.error "'scrivito' is undefined, the content browser will not be available"
4
+ $ ->
5
+ if !scrivito?
6
+ console.log "possible reason: '//= require scrivito_sdk' is missing"
7
+ else
8
+ console.log "possible reason: 'scrivito_sdk'/'scrivito_after_content_tags' is included after 'scrivito_content_browser'"
9
+ return
10
+
11
+ scrivito.content_browser = do ->
12
+ thumbnailViewButtonSelector: '.editing-button-view'
13
+ options: {}
14
+ filters: {}
15
+ filter_defaults:
16
+ upload: {}
17
+
18
+ # The content browser supports operations like +delete+ and +edit+ of resources that require a page
19
+ # reload, so that all references of the resources get updated.
20
+ reload: false
21
+
22
+ _getBatchSize: ->
23
+ @batchSize ||= 20
24
+
25
+ _getThumbnailSize: ->
26
+ @thumbnailSize ||= 'normal'
27
+
28
+ _setThumbnailSize: (value) ->
29
+ @thumbnailSize = value
30
+
31
+ _appendFilterItemTo: (list, options) ->
32
+ title = options.title || 'missing title'
33
+ icon = options.icon || 'scrivito-content-browser-icon-generic'
34
+ query = options.query
35
+ classname = options.classname || 'filter'
36
+
37
+ icon = icon.replace 'editing-icon', 'scrivito-content-browser-icon' # backwards compatibility
38
+
39
+ @_filterTemplate(title, icon, query)
40
+ .addClass(classname)
41
+ .appendTo(list)
42
+
43
+ _appendSeparatorTo: (list) ->
44
+ $('<li></li>')
45
+ .addClass('separator')
46
+ .appendTo(list)
47
+
48
+ _filterListTemplate: (filters) ->
49
+ list = $('<ul></ul>')
50
+ .addClass('scrivito-content-browser-filter-items')
51
+
52
+ @_appendFilterItemTo list,
53
+ title: 'Selected <span class="scrivito-content-browser-counter selected-total"></span>',
54
+ icon: 'scrivito-content-browser-icon-ok',
55
+ classname: 'selected-filter'
56
+
57
+ @_appendSeparatorTo list
58
+
59
+ for name, options of filters
60
+ @_appendFilterItemTo list, options
61
+
62
+ list
63
+
64
+ _loadFilter: () ->
65
+ filters = @_selectedFilters()
66
+ wrapper = @modal.find('.scrivito-content-browser-filter')
67
+
68
+ @_filterListTemplate(filters)
69
+ .appendTo(wrapper)
70
+
71
+ _activateInitialFilter: () ->
72
+ @_defaultFilter().trigger('click')
73
+
74
+ _selectedFilters: ->
75
+ availableFilters = @filters
76
+ selectedFilters = @options.filters
77
+ filters = availableFilters
78
+
79
+ if selectedFilters?
80
+ unless $.isArray(selectedFilters)
81
+ selectedFilters = new Array(selectedFilters)
82
+
83
+ filters = {}
84
+
85
+ for filterId, filter of availableFilters
86
+ if filterId in selectedFilters
87
+ filters[filterId] = filter
88
+
89
+ filters
90
+
91
+ _defaultFilter: ->
92
+ @_filterItems().first()
93
+
94
+ _getFilterQuery: (filter) ->
95
+ filter.data('query')
96
+
97
+ _defaultQuery: ->
98
+ @_getFilterQuery(@_defaultFilter())
99
+
100
+ _activeQuery: ->
101
+ filter = @_filterItems().filter('.active')
102
+ @_getFilterQuery(filter)
103
+
104
+ _filterItems: ->
105
+ @modal.find('ul.scrivito-content-browser-filter-items li')
106
+
107
+ _deactivateAllFilter: ->
108
+ @_getSearch().val('')
109
+ @_filterItems().removeClass('active')
110
+
111
+ _triggerFilter: (filter) ->
112
+ @_deactivateAllFilter()
113
+
114
+ filter.addClass('active')
115
+
116
+ query = @_getFilterQuery(filter)
117
+ @_renderPlaceholder(query)
118
+
119
+ _triggerSelectedFilter: (filter) ->
120
+ if @selected.length > 0
121
+ query = @_prepareQuery(scrivito.obj_where('id', 'equals', @selected))
122
+ filter.data('query', query)
123
+ else
124
+ filter.removeData('query')
125
+
126
+ @_triggerFilter(filter)
127
+
128
+ _filterTemplate: (title, icon, query) ->
129
+ filter = $('<li></li>')
130
+
131
+ if query?
132
+ query = @_prepareQuery(query)
133
+ filter.data('query', query)
134
+
135
+ icon = $('<span></span>')
136
+ .addClass('scrivito-content-browser-icon')
137
+ .addClass(icon)
138
+ .appendTo(filter)
139
+
140
+ title = $('<span></span>')
141
+ .addClass('scrivito-content-browser-filter-name')
142
+ .html(title)
143
+ .appendTo(filter)
144
+
145
+ filter
146
+
147
+ _prepareQuery: (query) ->
148
+ query.clone()
149
+ .order('_last_changed')
150
+ .reverse_order()
151
+ .format('content_browser')
152
+
153
+ _save: ->
154
+ @_promise.resolve(@selected)
155
+ @close()
156
+
157
+ _delete: ->
158
+ $.each @selected, (index, id) =>
159
+ item = @_getItemContainer(id)
160
+ @_itemLoading(item)
161
+
162
+ scrivito.delete_obj(id).then =>
163
+ @modal.trigger('resource_change.content_browser')
164
+ item.remove()
165
+
166
+ @_deselectAllItems()
167
+
168
+ _getItemId: (item) ->
169
+ $(item).closest('li.content-browser-item').data('id')
170
+
171
+ _getItemContainer: (id) ->
172
+ $('li.content-browser-item').filter ->
173
+ id == $(this).data('id')
174
+
175
+ _selectItem: (item) ->
176
+ if (item.hasClass('active'))
177
+ @_removeItem(item)
178
+ else
179
+ if @options.selectionMode == 'single'
180
+ @_deselectAllItems()
181
+
182
+ @_addItem(item)
183
+
184
+ _addItem: (item) ->
185
+ @_activateItem(item)
186
+
187
+ id = @_getItemId(item)
188
+
189
+ @selected.push(id)
190
+ @_setSelected($.unique(@selected))
191
+
192
+ _removeItem: (item) ->
193
+ @_deactivateItem(item)
194
+
195
+ selected = @selected.filter (id) =>
196
+ id != @_getItemId(item)
197
+
198
+ @_setSelected(selected)
199
+
200
+ _activateItem: (item) ->
201
+ $(item).addClass('active')
202
+
203
+ _deactivateItem: (item) ->
204
+ $(item).removeClass('active')
205
+
206
+ _changeSelectedTotal: ->
207
+ @modal.find('.selected-total').html(@selected.length)
208
+
209
+ _setSelected: (value) ->
210
+ @selected = value || @options.selection || []
211
+ @_changeSelectedTotal()
212
+
213
+ _deselectAllItems: ->
214
+ @_setSelected([])
215
+ @modal.find('li.content-browser-item .select-item.active').removeClass('active')
216
+
217
+ _getItems: ->
218
+ @modal.find('.scrivito-content-browser-items')
219
+
220
+ _getContainer: ->
221
+ @modal.find('.scrivito-content-browser-thumbnails')
222
+
223
+ _itemsPlaceholder: (count) ->
224
+ size = @_getThumbnailSize()
225
+
226
+ list = $('<ul></ul>')
227
+ .addClass('items scrivito-content-browser-thumbnails')
228
+ .addClass(size)
229
+
230
+ content = for index in [0...count] by 1
231
+ itemTemplate = @_itemPlaceholderTemplate(index)
232
+ list.append(itemTemplate)
233
+
234
+ @_getItems().html(content)
235
+
236
+ _itemPlaceholderTemplate: (index) ->
237
+ item = $('<li></li>')
238
+ .addClass('content-browser-item')
239
+ .attr('data-index', index)
240
+
241
+ @_itemLoading(item)
242
+
243
+ _itemLoading: (item) ->
244
+ loading = @_loadingTemplate()
245
+ $(item).html(loading)
246
+
247
+ _renderPlaceholder: (query) ->
248
+ @_getItems()
249
+ .empty()
250
+
251
+ if query?
252
+ @_getItems().html(@_loadingTemplate())
253
+
254
+ query
255
+ .batch_size(@_getBatchSize())
256
+
257
+ query.size()
258
+ .done (total) =>
259
+ if total > 0
260
+ @_itemsPlaceholder(total)
261
+ @_renderItems(query)
262
+ else
263
+ @_getItems().empty()
264
+
265
+ _renderItems: (query, index = 0) ->
266
+ query.load_batch()
267
+ .done (result, next) =>
268
+ objects = result.hits
269
+ @_replacePlaceholder(objects, index)
270
+
271
+ if next?
272
+ start = index + objects.length
273
+ @_renderItems(next, start)
274
+
275
+ _replacePlaceholder: (objects, startIndex) ->
276
+ $(objects).each (index, object) =>
277
+ elementIndex = startIndex + index
278
+ template = @_itemTemplate(object)
279
+
280
+ @modal.find("li.content-browser-item[data-index=#{elementIndex}]")
281
+ .html(template)
282
+ .data('id', object.id)
283
+
284
+ _itemTemplate: (object) ->
285
+ url = object.preview
286
+ title = object.title || object.id
287
+ id = object.id
288
+
289
+ wrapper = $('<div></div>')
290
+ .addClass('scrivito-content-browser-item-wrapper')
291
+
292
+ preview = $('<div></div>')
293
+ .addClass('scrivito-content-browser-preview')
294
+ .appendTo(wrapper)
295
+
296
+ inspect = $('<span></span>')
297
+ .addClass('scrivito-content-browser-inspect')
298
+ .appendTo(wrapper)
299
+
300
+ image = if url?
301
+ $('<img />')
302
+ .attr('src', url)
303
+ else
304
+ $('<span></span>')
305
+ .addClass('scrivito-content-browser-icon')
306
+ .addClass('scrivito-content-browser-icon-generic')
307
+
308
+ image.appendTo(preview)
309
+
310
+ meta = $('<div></div>')
311
+ .addClass('scrivito-content-browser-meta')
312
+ .appendTo(wrapper)
313
+
314
+ title = $('<span></span>')
315
+ .addClass('scrivito-content-browser-thumbnails-name')
316
+ .html(title)
317
+ .appendTo(meta)
318
+
319
+ select = $('<span></span>')
320
+ .addClass('scrivito-content-browser-thumbnails-select select-item')
321
+ .appendTo(title)
322
+
323
+ if id in @selected
324
+ select.addClass('active')
325
+
326
+ wrapper
327
+
328
+ _getSearch: ->
329
+ @modal.find('input.search-field')
330
+
331
+ _triggerSearch: ->
332
+ term = @_getSearch().val()
333
+ query = @_prepareQuery(@_activeQuery())
334
+
335
+ if term? && term.length > 0
336
+ query.and('*', 'contains_prefix', term)
337
+
338
+ @_renderPlaceholder(query)
339
+
340
+ _initializeBindings: ->
341
+ $(window).resize =>
342
+ @_center(@modal)
343
+
344
+ @modal.on 'keyup', 'input.search-field', (event) =>
345
+ if event.keyCode == 13
346
+ @_triggerSearch()
347
+
348
+ @modal.on 'click', 'button.search-field-button', (event) =>
349
+ event.preventDefault()
350
+ @_triggerSearch()
351
+
352
+ @modal.on 'click', 'li.content-browser-item', (event) =>
353
+ unless $(event.target).hasClass('scrivito-content-browser-inspect')
354
+ item = $(event.currentTarget).find('.select-item')
355
+ @_selectItem(item)
356
+
357
+ @modal.on 'click', '.content-browser-save', (event) =>
358
+ event.preventDefault()
359
+ @_save()
360
+
361
+ @modal.on 'click', '.content-browser-delete', (event) =>
362
+ event.preventDefault()
363
+ @_delete()
364
+
365
+ @modal.on 'click', '.content-browser-close', (event) =>
366
+ event.preventDefault()
367
+ @close()
368
+
369
+ @modal.on 'click', 'li.filter', (event) =>
370
+ event.preventDefault()
371
+ @_triggerFilter($(event.currentTarget))
372
+
373
+ @modal.on 'click', 'li.selected-filter', (event) =>
374
+ event.preventDefault()
375
+ @_triggerSelectedFilter($(event.currentTarget))
376
+
377
+ @modal.on 'click', @thumbnailViewButtonSelector, (event) =>
378
+ size = $(event.currentTarget).data('size')
379
+ @_changeThumbnailSize(size)
380
+
381
+ @modal.on 'resource_change.content_browser', (event) =>
382
+ @reload = true
383
+
384
+ $(document).on 'keyup.content_browser', (event) =>
385
+ event.stopImmediatePropagation()
386
+
387
+ if event.keyCode == 27
388
+ # Make sure to remove the event handler after
389
+ # +stopImmediatePropagation()+, otherwise all ESC keys are caught and
390
+ # not propagated.
391
+ $(document).off 'keyup.content_browser'
392
+
393
+ @close()
394
+
395
+ _loadModal: () ->
396
+ @overlay = $('<div></div>')
397
+ .addClass('editing-overlay show')
398
+ .appendTo($('body'))
399
+
400
+ innerHtml = """
401
+ <div class="scrivito-content-browser-body">
402
+ <div class="scrivito-content-browser-wrapper">
403
+ <div class="scrivito-content-browser-topbar">
404
+ <div class="scrivito-content-browser-search">
405
+ <input class="search-field" placeholder="Search", type="text" />
406
+ <button class="search-field-button">
407
+ Search
408
+ </button>
409
+ </div>
410
+ <span class="editing-button-view" data-size="normal-list">
411
+ <span class="scrivito-content-browser-icon scrivito-content-browser-icon-list-medium"
412
+ title="List view"></span>
413
+ </span>
414
+ <span class="editing-button-view" data-size="large">
415
+ <span class="scrivito-content-browser-icon scrivito-content-browser-icon-th-large"
416
+ title="Large thumbnails"></span>
417
+ </span>
418
+ <span class="editing-button-view" data-size="big">
419
+ <span class="scrivito-content-browser-icon scrivito-content-browser-icon-th"
420
+ title="Big thumbnails"></span>
421
+ </span>
422
+ <span class="editing-button-view" data-size="normal">
423
+ <span class="scrivito-content-browser-icon scrivito-content-browser-icon-th-medium"
424
+ title="Thumbnails"></span>
425
+ </span>
426
+ <span class="editing-button-view" data-size="small">
427
+ <span class="scrivito-content-browser-icon scrivito-content-browser-icon-th-small"
428
+ title="Small thumbnails"></span>
429
+ </span>
430
+ </div>
431
+ <div class="scrivito-content-browser-filter"></div>
432
+ <div class="scrivito-content-browser-items"></div>
433
+ </div>
434
+ <div class="scrivito-content-browser-inspector"></div>
435
+ </div>
436
+ <div class="scrivito-content-browser-footer">
437
+ <a class="editing-button content-browser-close">
438
+ Cancel
439
+ </a>
440
+ <a class="editing-button editing-green content-browser-save">
441
+ Select
442
+ <span class="scrivito-content-browser-counter selected-total"></span>
443
+ </a>
444
+ <a class="editing-button editing-red content-browser-delete">
445
+ Delete
446
+ <span class="scrivito-content-browser-counter selected-total"></span>
447
+ </a>
448
+ </div>
449
+ """
450
+
451
+ @modal = $('<div></div>')
452
+ .addClass('scrivito-content-browser show')
453
+ .attr('id', 'scrivito-content-browser')
454
+ .html(innerHtml)
455
+ .appendTo($('body'))
456
+
457
+ @_center(@modal)
458
+
459
+ @_initializeBindings()
460
+
461
+ _center: (domElement) ->
462
+ if domElement
463
+ domElement = $(domElement)
464
+ domElement.css(
465
+ marginLeft: -domElement.innerWidth() / 2
466
+ marginTop: -domElement.innerHeight() / 2
467
+ left: '50%'
468
+ )
469
+
470
+ _loadingTemplate: ->
471
+ icon = $('<i></i>')
472
+ .addClass('scrivito-content-browser-icon scrivito-content-browser-icon-refresh')
473
+
474
+ $('<div></div>')
475
+ .addClass('scrivito-content-browser-loading')
476
+ .html(icon)
477
+
478
+ _changeThumbnailSize: (size) ->
479
+ size ||= @_getThumbnailSize()
480
+ @_setThumbnailSize(size)
481
+
482
+ transitionListener = 'webkitTransitionEnd.content_browser otransitionend.content_browser oTransitionEnd.content_browser msTransitionEnd.content_browser transitionend.content_browser'
483
+ @modal.on transitionListener, 'li.content-browser-item', (event) =>
484
+ @modal.off transitionListener
485
+
486
+ @_getContainer()
487
+ .removeClass('small normal big large normal-list')
488
+ .addClass(size)
489
+
490
+ @modal.find(@thumbnailViewButtonSelector)
491
+ .removeClass('active')
492
+ .filter("[data-size='#{size}']")
493
+ .addClass('active')
494
+
495
+ close: ->
496
+ @_promise.reject() if @_promise.state() == 'pending'
497
+
498
+ @overlay.remove()
499
+ @modal.remove()
500
+
501
+ if @reload
502
+ $('body').trigger('infopark_reload')
503
+
504
+ open: (options) ->
505
+ @options = options
506
+
507
+ @_loadModal()
508
+ @_loadFilter()
509
+ @_setSelected()
510
+ @_renderPlaceholder(@_defaultQuery())
511
+ @_changeThumbnailSize()
512
+ @_activateInitialFilter()
513
+
514
+ @_inspector.init(@modal)
515
+ @_uploader.init(@modal)
516
+
517
+ @_uploader.onUploadStart = (files) =>
518
+ @upload_errors = false
519
+
520
+ @_uploader.onUploadFailure = (errors) =>
521
+ @upload_errors = errors
522
+
523
+ @_uploader.onUploadSuccess = (objs) =>
524
+ @_renderPlaceholder(@_activeQuery()) unless @upload_errors
525
+
526
+ @_promise = $.Deferred()
527
+ return @_promise
@@ -0,0 +1,22 @@
1
+ @Resourcebrowser = do ->
2
+ filters: {}
3
+ open: (options) ->
4
+ if Object.keys(@filters).length > 0
5
+ console.log "'Resourcebrowser.filters' is deprecated, please use 'scrivito.content_browser.filters'"
6
+ scrivito.content_browser.filters = @filters
7
+
8
+ if Object.keys(ResourcebrowserUploader.mimeTypeMapping).sort().join(",") != "image/*,video/*"
9
+ console.log "'ResourcebrowserUploader.mimeTypeMapping' is deprecated, please use 'scrivito.content_browser.filter_defaults.upload'"
10
+ scrivito.content_browser.filter_defaults.upload = ResourcebrowserUploader.mimeTypeMapping
11
+
12
+ if options.onSave?
13
+ console.log "Option 'onSave' is deprecated, please use 'scrivito.content_browser.open().done'"
14
+
15
+ console.log "'Resourcebrowser.open' is deprecated, please use 'scrivito.content_browser.open'"
16
+ scrivito.content_browser.open(options).done (selected) ->
17
+ options.onSave(selected) if options.onSave?
18
+
19
+ @ResourcebrowserUploader = do ->
20
+ mimeTypeMapping:
21
+ 'image/*': 'Image'
22
+ 'video/*': 'Video'