Scrivito 0.40.0 Release Notes

Breaking changes

Unified SDK gem

The Scrivito SDK gem to include in the “Gemfile” of the Rails application is now “scrivito.” It depends on the “scrivito_sdk” and “scrivito_editors” gems, which need to be removed from the “Gemfile” if they were specified there before.

Separation of the UI and the application assets

In previous versions of Scrivito, the in-place editing interface was part of the application page: the assets of the UI were loaded into the application window and executed in the context of the application. This caused several problems:

  • Cumbersome JavaScript dependecies with a risk of conflicts between libraries which the Scrivito UI included and those included by the application.
  • CSS conflicts and problems with assigning the correct Z-index.
  • The "preview" of the page was not realistic, since it still included assets of the UI, which could potentially change the look-and-feel of application pages.
  • In order to be able to display the Scrivito UI, the application has to include special assets and markup. Views of the application, which did not include the assets and the markup (for example application error pages), could not display the UI.

In order to avoid these problems, the Scrivito UI now renders the application page in a special iFrame, so that the browser window of the UI and the application are different and can't interfere.

Enabling the iFrame

For the editor, this change is transparent: the UI looks and feels almost as before, but in the newest Scrivito version the host application needs to include a special layout view template, scrivito_dialog.html.* underneath app/views/layouts/, in order to be able to display details dialogs.

With new applications, this template will be generated by the install generator. Applications for which the Scrivito SDK is upgraded can simply run the install generator again to generate the missing template: rails g scrivito:install.

Note: the scrivito_dialog.html.* template must include all Scrivito assets you normally include in application.js or application.css.

New filter options

The Content Browser now lets you configure the displayed filters in more detail. First of all, there are three different types now:

  • tree filters
  • radio_button filters
  • check_box filters

The Tree Filter is an extension of the filters already available in the previous content browser version. It lets you arrange the filter nodes hierarchically and thus group them logically. This allows you to concisely present even a rather complex filter set.

The Radio Button and Check Box filters allow you to present filter options as either radio or check_box buttons, giving the user the possibility to further restrict the results obtained by the selected filter. Check Boxes allow the editor to select multiple items while Radio Buttons only allow a single item to be selected at a time. These filters cannot be organised hierarchically.

In addition to the new filter types, there are several new options for defining how the filters are presented to the user when the Content Browser is first opened:

  • expanded - the children of a filter are initially visible
  • selected - preselects a filter item
  • icon - lets you specify an icon

To define what a filter returns, you can either use the known query option or the new Field-Operator-Value (FOV) options. The query option has precedence over the FOV options and overrides them if present. The FOV options can be specified using the field, operator and value keys which are equivalent to the arguments passed to scrivito.obj_where. You should prefer using the FOV options because they enable the Content Browser to recognize and further analyze the structure of the query. With hierarchical filters, field and operator may be specified on a parent filter level.

A full filter definition might look like this:

scrivito.content_browser.filters =
  obj_class:
    field: '_obj_class'
    options:
      binary_resources:
        expanded: true,
        value: ['Pdf', 'Image']
        icon: 'image'
        options:
          images:
            selected: true
            title: 'Images'
            value: 'Image'
          pdf:
            title: 'PDFs'
            value: 'Pdf'
      other_resources:
        value: ['Contact', 'Location']
        options:
          contacts:
            title: 'Contacts'
            value: 'Contact'
          location:
            title: 'Locations'
            value: 'Location'

  image_size:
    title: 'Image Size'
    field: 'size'
    type: 'radio_button'
    expanded: true
    options:
      thumbnail:
        title: 'Thumbnail'
      content:
        title: 'Page'
      banner:
        title: 'Banner'

  languages:
    title: 'Languages'
    field: 'language'
    type: 'check_box'
    expanded: true
    options:
      en:
        title: 'English'
      fr:
        title: 'French'
      es:
        title: 'Spanish'

This definition would result in the list of filters that can be seen on the left hand side of the screenshot below.

Migration

Migrating an old filter definition to the new format is easy. Simply add the old definition as it is to the option key of a new filter entry. If you used the icon option, you may need to remove the scrivito-content_browser-icon prefix. For example:

# previously
images:
  title: 'Images',
  query: scrivito.obj_where('_obj_class', 'equals', 'Image')
  icon: 'scrivito-content_browser-icon-image'

# new
legacy:
  options:
    images:
      title: 'Images',
      query: scrivito.obj_where('_obj_class', 'equals', 'Image')
      icon: 'image'

Other breaking changes

  • The method for creating a copy of a widget was renamed from clone to copy to keep the API in sync with Obj#copy. The usage of the method has not changed. You can copy a widget whose ID is widget_id from the homepage to a sub_page using the following code:
    sub_page.update(widget_field: sub_page.widget_field + [homepage.widgets['widget_id'].copy])
  • Scrivito::BasicWidget#copy now includes fields of the widget type. Copying widgets from widget fields now also includes the widget fields contained in these widgets.
  • The Scrivito::ObjsCollection class has been renamed to Scrivito::ObjCollection, and the Scrivito::MembershipsCollection class has been renamed to Scrivito::MembershipCollection in order to have more convenient naming all over the collection classes in the SDK.
  • Scrivito::ObjClass.all now returns a Scrivito::ObjClassCollection.
  • Triggering the scrivito_reload JS event has been deprecated and will be removed in version 1.0.0. Please use the new reload jQuery method instead. This change was made because the JS event was too powerful and often led to hard-to-debug issues due to many side effects, which the method doesn't have. Please replace all $.trigger("scrivito_reload") calls with $.scrivito("reload").
  • Previously, original content was updated after the promise returned by $.scrivito("save") was resolved. Now, $.scrivito("save") will immediately update the original content (even if the promise has not yet been resolved):

    var scrivito_field = $('…');
    scrivito_field.scrivito('content');
    // > 'old content'
    scrivito_field.save('new content');
    
    // Saving…
    scrivito_field.scrivito('content');
    // > 'new content'
    
    // Finished saving.
    scrivito_field.scrivito('content');
    // > 'new content'
    

New features and improvements

Restoring widgets

In the “All changes” and “Deletions” view modes, the user interface now lets you restore deleted widgets.

Copying widget hierarchies

Copying a widget via the UI now also includes all the widgets contained in the copied widget.

Also, Scrivito::BasicWidget#copy now includes fields of the widget type including the widgets contained in them.

API for registering and looking up default object classes for content types

When uploading content to the CMS by means of the Content Browser, an object class that fits the content type needs to be determined. For this and, of course, application-specific use cases, the SDK now offers an API for registering default object classes for content types:

scrivito.register_default_obj_class_for_content_type(mapping)

Provide a mapping that consists of key-value pairs where each pair is made up of a content type pattern as the key and an object class name as the value. The content type patterns may include wildcards either in the file type part or both content type parts. When looking up an object class, the most specific match will be used. The more wildcards the key of a pair contains, the less specific it is. You can register one or more defaults at once and also override the existing defaults.

The Scrivito SDK initially includes two mappings: 

  • image/* -> 'Image'
  • */* -> 'Download'

To look up a default, you can use scrivito.default_obj_class_for_content_type(content_type), passing the content type in question as a string. Examples:

scrivito.register_default_obj_class_for_content_type({
  'audio/mp3': 'MyMp3', // Register a default for all MP3s.
  'audio/*': 'MyAudio' // Register a default for all other audio files.
});

scrivito.register_default_obj_class_for_content_type({
  'image/*': 'MyImage', // Override factory default for image files.
  'image/png': 'MyPng', // Register default for PNG images.
  '*/*': 'MyDownload' // Override factory default for all other files.
});

scrivito.default_obj_class_for_content_type('image/png');
//> 'MyPng'
scrivito.default_obj_class_for_content_type('image/gif');
//> 'MyImage'
scrivito.default_obj_class_for_content_type('audio/wav');
//> 'MyAudio'
scrivito.default_obj_class_for_content_type('spam/eggs');
//> 'MyDownload'

Also, the Download model has been added to the install generator. In order to add the new model to an existing application, please re-run the generator: rails g scrivito:install

Binary editor

The Scrivito Editors gem now includes an editor for attributes of the binary type. Giving users a means to add and exchange binary content contained in such attributes is as simple as adding a scrivito_tag or scrivito_image_tag to your markup. A user can now drop a file onto binary elements part of a page. This causes the binary content to be saved to the CMS.

By default, binaries can only be exchanged and not deleted. If you wish to provide a means for deleting binary content contained in binary attributes, simply add the data-scrivito-editors-allow-delete option to the scrivito_tag. This will enable users to remove the binary content by the click of a button.

Other improvements

  • The Scrivito editors gem now includes the latest Redactor 10 version. If you see Redactor errors like "no such method" in the JavaScript console, check for outdated copies of the HTML editor in the asset folder of your app. These copies may have been needed in order to modify the behavior of the HTML editor. Please delete the old assets and take a look at the new scrivito.editors.html_editor.redactor.options configuration.
  • Redactor options can now be set globally by means of a new JavaScript API:
    // Example: hide the HTML source button for HTML fields
    scrivito.editors.html_editor.redactor.options = { buttonSource: false }
  • You can now access the widgets part of an Obj by their ID. This also includes widgets contained in widgets. If, for example, you have an obj and want to get at its widget whose ID is widget_id, use the following code:
    obj.widgets['widget_id']
  • Initializing external libraries used with Scrivito often required duplicating code. The library had to be initialized when the DOM was ready for normal website visitors, and also in the Scrivito content callback invoked after content was changed by editors. Now, it is no longer necessary to duplicate code because you can attach the initialization code to the content callback. The callback is triggered when the DOM is ready, whether in-place editing is active or not. This keeps your code nice and DRY. The API of the callback remains the same:
    scrivito.on('content', function(root_element) {   
      /* root_element will either be window.document or the widget that was changed */
    });
  • The JavaScript SDK now supports the content method for date attributes. This makes it possible to fetch a Javascript Date object for a date field. Suppose you have the following view code:
    <%= scrivito_tag :div, @obj, :my_date, id: 'my-date-attribute' %>
    You can access the Date object using:
    $('#my-date-attribute').scrivito('content')
    This feature is used by the date editor to prevent errors related to Rails' date localization.
  • The Javascript Search API now lets you combine queries using the new and method. It adds all the predicates of the second query to the first one. Other query properties such as batch_size or order are not changed when adding another query.
    var blog_posts = scrivito.obj_where('_obj_class', 'equals', 'BlogPost'); 
    var only_english = scrivito.obj_where('language', 'equals', 'en');  
    blog_posts.and(only_english);
    This example changes the query for finding BlogPosts so that it only returns the English-language ones by adding the only_english query to it.
  • The widget generator now enforces consistent widget names ending with Widget. For example, both rails g scrivito:widget Headline and rails g scrivito:widget HeadlineWidget generate a widget named HeadlineWidget (headline_widget.rb).
  • Previously, a Rails bug (http://git.io/Gzo13Q) prevented long queries from being cached properly. The SDK now provides a workaround for this issue.
  • The Scrivito editors gem no longer causes JavaScript errors for enum or multienum fields rendered by means of scrivito_tag.
  • The date editor keeps the time values when editing.
  • The date editor saves its content without producing NaN errors in Safari and Firefox.
  • With Google Chrome, leaving the text editor no longer causes line breaks to get lost.
  • Markup is no longer modified if the editor is closed without having changed something. HTML imported to Scrivito is reformatted when it is edited (e. g., tags are converted to lower case). This resulted in changes in the diff view, even if nothing had been edited.
  • If possible, the input caret now appears at the point the user clicked. However, if complex HTML text is rendered (e.g. if a block is passed to scrivito_tag), the caret shows up at the bottom of the area.
  • Fixed a CSS problem with some parts of the footer being not visible.
  • Added the previously missing Download model to the install generator
  • Fixed support for anchors when accessing a page as an authenticated editor and being redirected to the Scrivito UI.
  • Fixed problem with calling $.scrivito('reload') in the details dialog.
  • Fixed a problem with displaying the UI on pages that don't include the SDK (e.g. static pages or error pages generated by Rails).
  • Fixed a problem with saving links and linklists using the JS API.
  • Resolved an issue where the UI was still visible after logging out.
  • In the migration working copy, changes to widgets cannot be reverted anymore.