# Sanity check
if !scrivito?
console.error "'scrivito' is undefined, the content browser will not be available"
$ ->
if !scrivito?
console.log "possible reason: '//= require scrivito_sdk' is missing"
else
console.log "possible reason: 'scrivito_sdk'/'scrivito_after_content_tags' is included after 'scrivito_content_browser'"
return
scrivito.content_browser = do ->
thumbnailViewButtonSelector: '.editing-button-view'
options: {}
filters: {}
filter_defaults:
upload: {}
# The content browser supports operations like +delete+ and +edit+ of resources that require a page
# reload, so that all references of the resources get updated.
reload: false
_getBatchSize: ->
@batchSize ||= 20
_getThumbnailSize: ->
@thumbnailSize ||= 'normal'
_setThumbnailSize: (value) ->
@thumbnailSize = value
_appendFilterItemTo: (list, options) ->
title = options.title || 'missing title'
icon = options.icon || 'scrivito-content-browser-icon-generic'
query = options.query
classname = options.classname || 'filter'
icon = icon.replace 'editing-icon', 'scrivito-content-browser-icon' # backwards compatibility
@_filterTemplate(title, icon, query)
.addClass(classname)
.appendTo(list)
_appendSeparatorTo: (list) ->
$('
')
.addClass('separator')
.appendTo(list)
_filterListTemplate: (filters) ->
list = $('')
.addClass('scrivito-content-browser-filter-items')
@_appendFilterItemTo list,
title: 'Selected ',
icon: 'scrivito-content-browser-icon-ok',
classname: 'selected-filter'
@_appendSeparatorTo list
for name, options of filters
@_appendFilterItemTo list, options
list
_loadFilter: () ->
filters = @_selectedFilters()
wrapper = @modal.find('.scrivito-content-browser-filter')
@_filterListTemplate(filters)
.appendTo(wrapper)
_activateInitialFilter: () ->
@_defaultFilter().trigger('click')
_selectedFilters: ->
availableFilters = @filters
selectedFilters = @options.filters
filters = availableFilters
if selectedFilters?
unless $.isArray(selectedFilters)
selectedFilters = new Array(selectedFilters)
filters = {}
for filterId, filter of availableFilters
if filterId in selectedFilters
filters[filterId] = filter
filters
_defaultFilter: ->
@_filterItems().first()
_getFilterQuery: (filter) ->
filter.data('query')
_defaultQuery: ->
@_getFilterQuery(@_defaultFilter())
_activeQuery: ->
filter = @_filterItems().filter('.active')
@_getFilterQuery(filter)
_filterItems: ->
@modal.find('ul.scrivito-content-browser-filter-items li')
_deactivateAllFilter: ->
@_getSearch().val('')
@_filterItems().removeClass('active')
_triggerFilter: (filter) ->
@_deactivateAllFilter()
filter.addClass('active')
query = @_getFilterQuery(filter)
@_renderPlaceholder(query)
_triggerSelectedFilter: (filter) ->
if @selected.length > 0
query = @_prepareQuery(scrivito.obj_where('id', 'equals', @selected))
filter.data('query', query)
else
filter.removeData('query')
@_triggerFilter(filter)
_filterTemplate: (title, icon, query) ->
filter = $('')
if query?
query = @_prepareQuery(query)
filter.data('query', query)
icon = $('')
.addClass('scrivito-content-browser-icon')
.addClass(icon)
.appendTo(filter)
title = $('')
.addClass('scrivito-content-browser-filter-name')
.html(title)
.appendTo(filter)
filter
_prepareQuery: (query) ->
query.clone()
.order('_last_changed')
.reverse_order()
.format('content_browser')
_save: ->
@_promise.resolve(@selected)
@close()
_delete: ->
$.each @selected, (index, id) =>
item = @_getItemContainer(id)
@_itemLoading(item)
scrivito.delete_obj(id).then =>
@modal.trigger('resource_change.content_browser')
item.remove()
@_deselectAllItems()
_getItemId: (item) ->
$(item).closest('li.content-browser-item').data('id')
_getItemContainer: (id) ->
$('li.content-browser-item').filter ->
id == $(this).data('id')
_selectItem: (item) ->
if (item.hasClass('active'))
@_removeItem(item)
else
if @options.selectionMode == 'single'
@_deselectAllItems()
@_addItem(item)
_addItem: (item) ->
@_activateItem(item)
id = @_getItemId(item)
@selected.push(id)
@_setSelected($.unique(@selected))
_removeItem: (item) ->
@_deactivateItem(item)
selected = @selected.filter (id) =>
id != @_getItemId(item)
@_setSelected(selected)
_activateItem: (item) ->
$(item).addClass('active')
_deactivateItem: (item) ->
$(item).removeClass('active')
_changeSelectedTotal: ->
@modal.find('.selected-total').html(@selected.length)
_setSelected: (value) ->
@selected = value || @options.selection || []
@_changeSelectedTotal()
_deselectAllItems: ->
@_setSelected([])
@modal.find('li.content-browser-item .select-item.active').removeClass('active')
_getItems: ->
@modal.find('.scrivito-content-browser-items')
_getContainer: ->
@modal.find('.scrivito-content-browser-thumbnails')
_itemsPlaceholder: (count) ->
size = @_getThumbnailSize()
list = $('')
.addClass('items scrivito-content-browser-thumbnails')
.addClass(size)
content = for index in [0...count] by 1
itemTemplate = @_itemPlaceholderTemplate(index)
list.append(itemTemplate)
@_getItems().html(content)
_itemPlaceholderTemplate: (index) ->
item = $('')
.addClass('content-browser-item')
.attr('data-index', index)
@_itemLoading(item)
_itemLoading: (item) ->
loading = @_loadingTemplate()
$(item).html(loading)
_renderPlaceholder: (query) ->
@_getItems()
.empty()
if query?
@_getItems().html(@_loadingTemplate())
query
.batch_size(@_getBatchSize())
query.size()
.done (total) =>
if total > 0
@_itemsPlaceholder(total)
@_renderItems(query)
else
@_getItems().empty()
_renderItems: (query, index = 0) ->
query.load_batch()
.done (result, next) =>
objects = result.hits
@_replacePlaceholder(objects, index)
if next?
start = index + objects.length
@_renderItems(next, start)
_replacePlaceholder: (objects, startIndex) ->
$(objects).each (index, object) =>
elementIndex = startIndex + index
template = @_itemTemplate(object)
@modal.find("li.content-browser-item[data-index=#{elementIndex}]")
.html(template)
.data('id', object.id)
_itemTemplate: (object) ->
url = object.preview
title = object.title || object.id
id = object.id
wrapper = $('')
.addClass('scrivito-content-browser-item-wrapper')
preview = $('')
.addClass('scrivito-content-browser-preview')
.appendTo(wrapper)
inspect = $('')
.addClass('scrivito-content-browser-inspect')
.appendTo(wrapper)
image = if url?
$('')
.attr('src', url)
else
$('')
.addClass('scrivito-content-browser-icon')
.addClass('scrivito-content-browser-icon-generic')
image.appendTo(preview)
meta = $('')
.addClass('scrivito-content-browser-meta')
.appendTo(wrapper)
title = $('')
.addClass('scrivito-content-browser-thumbnails-name')
.html(title)
.appendTo(meta)
select = $('')
.addClass('scrivito-content-browser-thumbnails-select select-item')
.appendTo(title)
if id in @selected
select.addClass('active')
wrapper
_getSearch: ->
@modal.find('input.search-field')
_triggerSearch: ->
term = @_getSearch().val()
query = @_prepareQuery(@_activeQuery())
if term? && term.length > 0
query.and('*', 'contains_prefix', term)
@_renderPlaceholder(query)
_initializeBindings: ->
$(window).resize =>
@_center(@modal)
@modal.on 'keyup', 'input.search-field', (event) =>
if event.keyCode == 13
@_triggerSearch()
@modal.on 'click', 'button.search-field-button', (event) =>
event.preventDefault()
@_triggerSearch()
@modal.on 'click', 'li.content-browser-item', (event) =>
unless $(event.target).hasClass('scrivito-content-browser-inspect')
item = $(event.currentTarget).find('.select-item')
@_selectItem(item)
@modal.on 'click', '.content-browser-save', (event) =>
event.preventDefault()
@_save()
@modal.on 'click', '.content-browser-delete', (event) =>
event.preventDefault()
@_delete()
@modal.on 'click', '.content-browser-close', (event) =>
event.preventDefault()
@close()
@modal.on 'click', 'li.filter', (event) =>
event.preventDefault()
@_triggerFilter($(event.currentTarget))
@modal.on 'click', 'li.selected-filter', (event) =>
event.preventDefault()
@_triggerSelectedFilter($(event.currentTarget))
@modal.on 'click', @thumbnailViewButtonSelector, (event) =>
size = $(event.currentTarget).data('size')
@_changeThumbnailSize(size)
@modal.on 'resource_change.content_browser', (event) =>
@reload = true
$(document).on 'keyup.content_browser', (event) =>
event.stopImmediatePropagation()
if event.keyCode == 27
# Make sure to remove the event handler after
# +stopImmediatePropagation()+, otherwise all ESC keys are caught and
# not propagated.
$(document).off 'keyup.content_browser'
@close()
_loadModal: () ->
@overlay = $('')
.addClass('editing-overlay show')
.appendTo($('body'))
innerHtml = """
"""
@modal = $('')
.addClass('scrivito-content-browser show')
.attr('id', 'scrivito-content-browser')
.html(innerHtml)
.appendTo($('body'))
@_center(@modal)
@_initializeBindings()
_center: (domElement) ->
if domElement
domElement = $(domElement)
domElement.css(
marginLeft: -domElement.innerWidth() / 2
marginTop: -domElement.innerHeight() / 2
left: '50%'
)
_loadingTemplate: ->
icon = $('')
.addClass('scrivito-content-browser-icon scrivito-content-browser-icon-refresh')
$('')
.addClass('scrivito-content-browser-loading')
.html(icon)
_changeThumbnailSize: (size) ->
size ||= @_getThumbnailSize()
@_setThumbnailSize(size)
transitionListener = 'webkitTransitionEnd.content_browser otransitionend.content_browser oTransitionEnd.content_browser msTransitionEnd.content_browser transitionend.content_browser'
@modal.on transitionListener, 'li.content-browser-item', (event) =>
@modal.off transitionListener
@_getContainer()
.removeClass('small normal big large normal-list')
.addClass(size)
@modal.find(@thumbnailViewButtonSelector)
.removeClass('active')
.filter("[data-size='#{size}']")
.addClass('active')
close: ->
@_promise.reject() if @_promise.state() == 'pending'
@overlay.remove()
@modal.remove()
if @reload
$('body').trigger('infopark_reload')
open: (options) ->
@options = options
@_loadModal()
@_loadFilter()
@_setSelected()
@_renderPlaceholder(@_defaultQuery())
@_changeThumbnailSize()
@_activateInitialFilter()
@_inspector.init(@modal)
@_uploader.init(@modal)
@_uploader.onUploadStart = (files) =>
@upload_errors = false
@_uploader.onUploadFailure = (errors) =>
@upload_errors = errors
@_uploader.onUploadSuccess = (objs) =>
@_renderPlaceholder(@_activeQuery()) unless @upload_errors
@_promise = $.Deferred()
return @_promise