scrivito_content_browser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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'