# 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