css/edit.css | 21 ++-
edit.info | 1 +
edit.module | 198 ++++++++------------
edit_aloha/edit_aloha.module | 28 +--
edit_aloha/js/createjs/drupalalohawidget.js | 156 +++++++++++++++
.../Plugin/edit/processed_text_editor/Aloha.php | 43 +++++
generate-core-patch.sh | 7 +-
grunt.js | 5 +-
includes/pages.inc | 48 ++---
js/app.js | 2 +-
js/backbone.drupalform.js | 14 +-
js/createjs/editable.js | 12 +-
js/createjs/editingWidgets/drupalalohawidget.js | 153 ---------------
.../editingWidgets/drupalcontenteditablewidget.js | 4 +-
js/createjs/editingWidgets/formwidget.js | 10 +-
js/edit.js | 6 +
js/util.js | 28 +--
js/viejs/EditService.js | 8 +-
js/views/modal-view.js | 2 +-
js/views/overlay-view.js | 2 +-
js/views/toolbar-view.js | 2 +-
lib/Drupal/edit/Ajax/BaseCommand.php | 52 +++++
lib/Drupal/edit/Ajax/FieldFormCommand.php | 27 +++
lib/Drupal/edit/Ajax/FieldFormSavedCommand.php | 28 +++
.../edit/Ajax/FieldFormValidationErrorsCommand.php | 28 +++
...RenderedWithoutTransformationFiltersCommand.php | 28 +++
lib/Drupal/edit/EditBundle.php | 26 +++
lib/Drupal/edit/Plugin/ProcessedTextEditorBase.php | 35 ++++
.../Plugin/Type/ProcessedTextEditorManager.php | 31 +++
lib/Drupal/edit/Tests/FieldEditorTest.php | 149 +++++++++++++++
text.patch | 8 +-
31 files changed, 781 insertions(+), 381 deletions(-)
diff --git a/css/edit.css b/css/edit.css
index 69de4f0..b270165 100644
--- a/css/edit.css
+++ b/css/edit.css
@@ -77,6 +77,9 @@
.toolbar .tray.edit.active {
z-index: 340;
}
+.toolbar .icon-edit.edit-nothing-editable-hidden {
+ display: none;
+}
@@ -109,7 +112,7 @@
}
.edit-field.edit-editable,
.edit-field.edit-type-direct .edit-editable {
- box-shadow: 0 0 1px 1px #4D9DE9;
+ box-shadow: 0 0 1px 1px #4d9de9;
}
/* Highlighted (hovered) editable. */
@@ -119,7 +122,7 @@
.edit-field.edit-editable.edit-highlighted,
.edit-form.edit-editable.edit-highlighted,
.edit-field.edit-type-direct .edit-editable.edit-highlighted {
- box-shadow: 0 0 1px 1px #0199FF, 0 0 3px 3px rgba(153, 153, 153, .5);
+ box-shadow: 0 0 1px 1px #0199ff, 0 0 3px 3px rgba(153, 153, 153, .5);
}
.edit-field.edit-editable.edit-highlighted.edit-validation-error,
.edit-form.edit-editable.edit-highlighted.edit-validation-error,
@@ -153,7 +156,7 @@
left: 40%;
box-shadow: 3px 3px 5px #333;
background-color: white;
- border: 1px solid #0199FF;
+ border: 1px solid #0199ff;
font-family: 'Droid sans', 'Lucida Grande', sans-serif;
}
@@ -198,7 +201,7 @@
left: -5px;
margin: 0;
border: none;
- box-shadow: 0 0 1 1px red, 0 0 3px 3px rgba(153, 153, 153, .5);
+ box-shadow: 0 0 1px 1px red, 0 0 3px 3px rgba(153, 153, 153, .5);
background-color: white;
}
@@ -215,7 +218,7 @@
.edit-form {
position: absolute;
z-index: 300;
- box-shadow: 0 0 30px 4px #4F4F4F;
+ box-shadow: 0 0 30px 4px #4f4f4f;
max-width: 35em;
}
@@ -249,6 +252,8 @@
margin: 0;
vertical-align: baseline;
z-index: 310;
+}
+.edit-toolbar-container {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
@@ -261,8 +266,8 @@
height: auto;
position: absolute;
bottom: 1px;
- box-shadow: 0 0 1px 1px #0199FF, 0 0 3px 3px rgba(153, 153, 153, .5);
- background: #FFF;
+ box-shadow: 0 0 1px 1px #0199ff, 0 0 3px 3px rgba(153, 153, 153, .5);
+ background: #fff;
}
/* The toolbar; these are not necessarily visible. */
@@ -292,7 +297,7 @@
float: left; /* LTR */
font-weight: bolder;
padding: 0 5px;
- background: #FFF url('../images/throbber.gif') no-repeat -60px 60px;
+ background: #fff url('../images/throbber.gif') no-repeat -60px 60px;
}
.edit-toolgroup.info.loading {
padding-right: 35px;
diff --git a/edit.info b/edit.info
index 5298534..3328601 100644
--- a/edit.info
+++ b/edit.info
@@ -4,3 +4,4 @@ package = Core
core = 8.x
dependencies[] = field
+dependencies[] = toolbar
diff --git a/edit.module b/edit.module
index 5df4a07..8740388 100644
--- a/edit.module
+++ b/edit.module
@@ -13,6 +13,7 @@
use Drupal\Core\Template\Attribute;
use Drupal\field\FieldInstance;
+use Drupal\edit\Plugin\Type\ProcessedTextEditorManager;
// @todo: POSTPONED_ON(Drupal core, http://drupal.org/node/1839516)
// Remove this when Entity Access API is ready.
@@ -40,9 +41,8 @@ function edit_menu() {
'access callback' => TRUE,
'page callback' => 'edit_field_edit',
'page arguments' => array(3, 4, 5, 6, 7),
- 'file' => 'includes/pages.inc',
- 'delivery callback'=> 'ajax_deliver',
'theme callback' => 'ajax_base_page_theme',
+ 'file' => 'includes/pages.inc',
);
$items['admin/render-without-transformations/field/%/%/%/%/%'] = array(
// Access is controlled after we have inspected the entity, which can't
@@ -51,9 +51,8 @@ function edit_menu() {
'access callback' => TRUE,
'page callback' => 'edit_text_field_render_without_transformation_filters',
'page arguments' => array(3, 4, 5, 6, 7),
- 'file' => 'includes/pages.inc',
- 'delivery callback'=> 'ajax_deliver',
'theme callback' => 'ajax_base_page_theme',
+ 'file' => 'includes/pages.inc',
);
return $items;
@@ -73,29 +72,33 @@ function edit_toolbar() {
'href' => '',
'html' => FALSE,
'attributes' => array(
- 'class' => array('icon', 'icon-edit'),
- ),
- // @todo: BLOCKED_ON(Drupal core, http://drupal.org/node/1847198)
- // This #post_render callback does not yet get called, which means that
- // even if zero fields on the current page are editable for the current
- // user, the "Edit" tab will still show up.
- '#post_render' => array(
- 'edit_toolbar_post_render',
+ 'class' => array('icon', 'icon-edit', 'edit-nothing-editable-hidden'),
),
),
'tray' => array(
+ '#heading' => t('In-place editing operations'),
'view_edit_toggle' => array(
- '#prefix' => '
' . t('In-place edit operations') . '
',
- 'content' => array(
- array(
- '#theme' => 'menu_local_task',
- '#link' => array('title' => t('View'), 'href' => current_path(), 'localized_options' => array('fragment' => 'view', 'attributes' => array('class' => array('edit_view-edit-toggle', 'edit-view')))),
- '#active' => TRUE,
+ '#theme' => 'links__toolbar_edit',
+ '#attributes' => array(
+ 'id' => 'edit_view-edit-toggles',
+ 'class' => 'menu',
+ ),
+ '#links' => array(
+ 'view' => array(
+ 'title' => t('View'),
+ 'href' => request_path(),
+ 'fragment' => 'view',
+ 'attributes' => array(
+ 'class' => array('edit_view-edit-toggle', 'edit-view'),
+ ),
),
- array(
- '#theme' => 'menu_local_task',
- '#link' => array('title' => t('Quick edit'), 'href' => current_path(), 'localized_options' => array('fragment' => 'quick-edit', 'attributes' => array('class' => array('edit_view-edit-toggle', 'edit-edit')))),
+ 'edit' => array(
+ 'title' => t('Quick edit'),
+ 'href' => request_path(),
+ 'fragment' => 'quick-edit',
+ 'attributes' => array(
+ 'class' => array('edit_view-edit-toggle', 'edit-edit'),
+ ),
),
),
'#attached' => array(
@@ -104,9 +107,6 @@ function edit_toolbar() {
),
),
),
- '#post_render' => array(
- 'edit_toolbar_post_render',
- ),
),
);
@@ -114,17 +114,6 @@ function edit_toolbar() {
}
/**
- * Post-render function to only show the Edit tab in the toolbar if relevant.
- *
- * When the user cannot edit any of the fields on the page, he should not be
- * given the possibility to toggle edit mode.
- */
-function edit_toolbar_post_render($html) {
- global $edit_toolbar;
- return ($edit_toolbar !== TRUE) ? '' : $html;
-}
-
-/**
* Implements hook_library().
*/
function edit_library_info() {
@@ -156,7 +145,6 @@ function edit_library_info() {
$path . '/js/createjs/storage.js' => array('defer' => TRUE),
$path . '/js/createjs/editingWidgets/formwidget.js' => array('defer' => TRUE),
$path . '/js/createjs/editingWidgets/drupalcontenteditablewidget.js' => array('defer' => TRUE),
- $path . '/js/createjs/editingWidgets/drupalalohawidget.js' => array('defer' => TRUE),
// Other.
$path . '/js/util.js' => array('defer' => TRUE),
$path . '/js/theme.js' => array('defer' => TRUE),
@@ -182,14 +170,10 @@ function edit_library_info() {
array('system', 'jquery.form'),
array('system', 'drupal.form'),
array('system', 'drupal.ajax'),
+ array('system', 'drupalSettings'),
),
);
- // Only add dependencies on the WYSIWYG editor when it's actually available.
- if (count(module_implements('edit_wysiwyg_info'))) {
- $libraries['edit']['dependencies'][] = _edit_get_wysiwyg_info('javascript library');
- }
-
return $libraries;
}
@@ -225,18 +209,15 @@ function edit_preprocess_field(&$variables) {
$entity_access = edit_entity_access('update', $entity->entityType(), $entity);
$field_access = field_access('edit', $field_name, $entity->entityType(), $entity);
- $editability = _edit_analyze_field_editability($items, $instance, $formatter_type);
- if ($entity_access && $field_access && $editability != 'disabled') {
- global $edit_toolbar;
- $edit_toolbar = TRUE;
-
+ $editor = _edit_get_field_editor($items, $instance, $formatter_type);
+ if ($entity_access && $field_access && $editor != 'disabled') {
// Mark this field as editable and provide metadata through data- attributes.
$variables['attributes']['data-edit-field-label'] = $instance->definition['label'];
$variables['attributes']['data-edit-id'] = $entity->entityType() . ':' . $entity->id() . ':' . $field_name . ':' . $langcode . ':' . $view_mode;
$variables['attributes']['class'][] = 'edit-field';
$variables['attributes']['class'][] = 'edit-allowed';
- $variables['attributes']['class'][] = 'edit-type-' . $editability;
- if ($editability == 'direct-with-wysiwyg') {
+ $variables['attributes']['class'][] = 'edit-type-' . $editor;
+ if ($editor == 'direct-with-wysiwyg') {
$variables['attributes']['class'][] = 'edit-type-direct';
$format_id = $entity->{$field_name}[$langcode][0]['format'];
_edit_preprocess_field_wysiwyg($variables, $format_id);
@@ -245,7 +226,7 @@ function edit_preprocess_field(&$variables) {
}
/**
- * Sets attributes on a field that have 'direct-with-wysiwyg' editability.
+ * Sets attributes on a field that have 'direct-with-wysiwyg' editor.
*
* @param array $variables
* An associative array containing: the key 'attributes'. See the
@@ -259,11 +240,6 @@ function _edit_preprocess_field_wysiwyg(&$variables, $format_id) {
// Let the WYSIWYG editor know the text format.
$variables['attributes']['data-edit-text-format'] = $format_id;
- // Ensure the WYSIWYG editor has the necessary text format related
- // metadata.
- $settings_callback = _edit_get_wysiwyg_info('javascript settings callback');
- $settings_callback();
-
// Let the JavaScript logic know whether transformation filters are used
// in this format, so it can decide whether to re-render the text or not.
$filter_types = filter_get_filter_types_by_format($format_id);
@@ -280,7 +256,7 @@ function _edit_preprocess_field_wysiwyg(&$variables, $format_id) {
}
/**
- * Determines editability given a field, its instance info and its formatter.
+ * Determines editor given a field, its instance info and its formatter.
*
* @param array $field
* The field's field array.
@@ -290,57 +266,57 @@ function _edit_preprocess_field_wysiwyg(&$variables, $format_id) {
* The field's formatter type name.
*
* @return string
- * The editability: 'disabled', 'form', 'direct' or 'direct-with-wysiwyg'.
+ * The editor: 'disabled', 'form', 'direct' or 'direct-with-wysiwyg'.
*/
-function _edit_analyze_field_editability($items, FieldInstance $instance, $formatter_type) {
+function _edit_get_field_editor($items, FieldInstance $instance, $formatter_type) {
$field_name = $instance['field_name'];
// If the formatter doesn't contain the edit property, default it to 'form'
- // editability, which should always work.
+ // editor, which should always work.
$formatter_info = field_info_formatter_types($formatter_type);
- if (empty($formatter_info['edit']['editability'])) {
- $formatter_info['edit']['editability'] = 'form';
+ if (empty($formatter_info['edit']['editor'])) {
+ $formatter_info['edit']['editor'] = 'form';
}
- $editability = $formatter_info['edit']['editability'];
+ $editor = $formatter_info['edit']['editor'];
// If editing is explicitly disabled for this field, return early to avoid
// any further processing.
- if ($editability == 'disabled') {
+ if ($editor == 'disabled') {
return;
}
// If directly editable, check the cardinality. If the cardinality is greater
// than 1, use a form to edit the field.
- if ($editability == 'direct') {
+ if ($editor == 'direct') {
$field = field_info_field($field_name);
if ($field['cardinality'] != 1) {
- $editability = 'form';
+ $editor = 'form';
}
}
// If still directly editable, check whether "regular" direct editing (almost
// bare contentEditable) editing should be used or WYSIWYG-based direct
// editing should be used. In the latter case
- if ($editability == 'direct') {
+ if ($editor == 'direct') {
// If this field is configured to not use text processing; it is plain text
// "regular" direct editing should be used, which is already set.
// On the other hand, if it is configured to use text processing; then we
- // must check whether 'direct-with-wysiwyg' or 'form' editability should be
+ // must check whether 'direct-with-wysiwyg' or 'form' editor should be
// used.
if (!empty($instance['settings']['text_processing'])) {
$format_id = $items[0]['format'];
- $editability = _edit_wysiwyg_analyze_field_editability($format_id);
+ $editor = _edit_wysiwyg_get_field_editor($format_id);
}
}
- return $editability;
+ return $editor;
}
/**
- * Determines editability given a directly editable field with text processing.
+ * Determines editor given a directly editable field with text processing.
*
- * Given a text field (with cardinality 1) that defaults to 'direct' editability
+ * Given a text field (with cardinality 1) that defaults to 'direct' editor
* and has text processing enabled, check whether the text format allows it to
* use WYSIWYG-powered direct editing or whether 'form' based editing needs to
* be used.
@@ -349,65 +325,57 @@ function _edit_analyze_field_editability($items, FieldInstance $instance, $forma
* The field's current text format.
*
* @return string
- * The editability: 'direct-with-wysiwyg' or 'form'.
+ * The editor: 'direct-with-wysiwyg' or 'form'.
*/
-function _edit_wysiwyg_analyze_field_editability($format_id = NULL) {
+function _edit_wysiwyg_get_field_editor($format_id = NULL) {
+ $wysiwyg_plugin = &drupal_static(__FUNCTION__);
+
// If no format is assigned yet, (e.g. when the field is still empty (NULL)),
// then provide form-based editing, so that the user is able to select a text
// format. (Direct editing doesn't allow the user to change the format.)
if (empty($format_id)) {
return 'form';
}
+
+ // NOTE: this code will pick the first processed text PropertyEditor widget
+ // plug-in that is available and consider that the only available choice.
+ // @todo: make it possible to have multiple processed text PropertyEditor
+ // widgets.
+ if (!isset($wysiwyg_plugin) && isset($format_id)) {
+ $definitions = drupal_container()->get('plugin.manager.edit.processed_text_editor')->getDefinitions();
+ if (count($definitions)) {
+ $plugin_ids = array_keys($definitions);
+ $plugin_id = $plugin_ids[0];
+ $wysiwyg_plugin = drupal_container()->get('plugin.manager.edit.processed_text_editor')->createInstance($plugin_id);
+ $wysiwyg_plugin->settingsAdded = FALSE;
+ }
+ }
+
// If no WYSIWYG editor is available, then fall back to form-based editing.
- elseif (count(_edit_get_wysiwyg_info()) == 0) {
+ if (!isset($wysiwyg_plugin)) {
return 'form';
}
// If the WYSIWYG editor is not compatible with the current format, then fall
// back to form-based editing.
else {
- $compatibility_callback = _edit_get_wysiwyg_info('format compatibility callback');
- if (!$compatibility_callback($format_id)) {
+ $match = $wysiwyg_plugin->checkFormatCompatibility($format_id);
+ if (!$match) {
return 'form';
}
- }
-
- return 'direct-with-wysiwyg';
-}
-
-/**
- * Retrieves a list of all available WYSIWYG integration for Edit. Only the
- * first is actually used.
- *
- * @todo Convert to the plug-in system!
- *
- * @param string $key
- * The key to get a value for.
- *
- * @see hook_edit_wysiwyg_info()
- * @see hook_edit_wysiwyg_info_alter()
- */
-function _edit_get_wysiwyg_info($key = NULL) {
- $edit_wysiwyg_info = &drupal_static(__FUNCTION__, array());
-
- if (empty($edit_wysiwyg_info)) {
- $cache = cache()->get('edit_wysiwyg_info');
- if ($cache === FALSE) {
- // Rebuild the cache and save it.
- $edit_wysiwyg_info = module_invoke_all('edit_wysiwyg_info');
- drupal_alter('edit_wysiwyg_info', $edit_wysiwyg_info);
- }
- else {
- $edit_wysiwyg_info = $cache->data;
+ else if ($match) {
+ // Only load the WYSIWYG editor's JavaScript if it hasn't been already.
+ if ($wysiwyg_plugin->settingsAdded === FALSE) {
+ $definition = $wysiwyg_plugin->getDefinition();
+ drupal_add_library($definition['library']['module'], $definition['library']['name']);
+ $wysiwyg_plugin->addJsSettings();
+
+ // Let Create.js know which WYSIWYG editor widget it should use.
+ drupal_add_js(array('edit' => array(
+ 'wysiwygEditorWidgetName' => $definition['propertyEditorName'],
+ )), 'setting');
+ $wysiwyg_plugin->settingsAdded = TRUE;
+ }
+ return 'direct-with-wysiwyg';
}
}
-
- if (isset($key)) {
- $modules = array_keys($edit_wysiwyg_info);
- $first = $modules[0];
-
- return $edit_wysiwyg_info[$first][$key];
- }
- else {
- return $edit_wysiwyg_info;
- }
}
diff --git a/edit_aloha/edit_aloha.module b/edit_aloha/edit_aloha.module
index f3b3c08..865bcb0 100644
--- a/edit_aloha/edit_aloha.module
+++ b/edit_aloha/edit_aloha.module
@@ -8,18 +8,6 @@
*/
/**
- * Implements hook_edit_wysiwyg_info().
- */
-function edit_aloha_edit_wysiwyg_info() {
- $info['edit_aloha'] = array(
- 'javascript library' => array('edit_aloha', 'aloha.edit'),
- 'format compatibility callback' => 'aloha_check_format_compatibility',
- 'javascript settings callback' => 'aloha_add_format_settings',
- );
- return $info;
-}
-
-/**
* Implements hook_library_info().
*/
function edit_aloha_library_info() {
@@ -28,26 +16,14 @@ function edit_aloha_library_info() {
'title' => 'Integrate Aloha Editor with the Edit module.',
'version' => ALOHA_VERSION,
'js' => array(
- // Configure Edit's JS to use aloha as the WYSIWYG.
- array(
- 'data' => array(
- 'edit' => array('wysiwyg' => 'aloha'),
- 'aloha' => array('settings' => array(
- // Ensure the Edit module can embed the rendered toolbar within
- // its own DOM infrastructure.
- 'DrupalUI' => array(
- 'renderOwnToolbarContainer' => FALSE,
- )
- ))
- ),
- 'type' => 'setting',
- ),
+ $module_path . '/js/createjs/drupalalohawidget.js' => array('defer' => TRUE),
),
'css' => array(
$module_path . '/css/drupal.aloha.edit.css',
),
'dependencies' => array(
array('aloha', 'aloha'),
+ array('edit', 'edit')
)
);
return $libraries;
diff --git a/edit_aloha/js/createjs/drupalalohawidget.js b/edit_aloha/js/createjs/drupalalohawidget.js
new file mode 100644
index 0000000..d020e8c
--- /dev/null
+++ b/edit_aloha/js/createjs/drupalalohawidget.js
@@ -0,0 +1,156 @@
+/**
+ * @file
+ * Override of Create.js' default Aloha Editor widget.
+ *
+ * NOTE: This does in fact use zero code of jQuery.create.alohaWidget.
+ */
+(function (jQuery, Drupal, drupalSettings) {
+
+"use strict";
+
+ jQuery.widget('Drupal.drupalAlohaWidget', jQuery.Create.alohaWidget, {
+
+ // @todo BLOCKED_ON(Create.js/VIE.js, how to restore original content when canceling editing)
+ // Actually use this when restoring original content, but for that we
+ // first need to know how to restore content in a Create.js context
+ originalTransformedContent: null,
+
+ /**
+ * Implements jQuery UI widget factory's _init() method.
+ *
+ * @todo: POSTPONED_ON(Create.js, https://github.com/bergie/create/issues/142)
+ * Get rid of this once that issue is solved.
+ */
+ _init: function() {},
+
+ /**
+ * Implements Create's _initialize() method.
+ */
+ _initialize: function() {
+ this._bindEvents();
+
+ // Immediately initialize Aloha, this can take some time. By doing it now
+ // already, it will most likely already be ready when the user actually
+ // wants to use Aloha Editor.
+ Drupal.aloha.init();
+ },
+
+ /**
+ * Binds to events.
+ *
+ * @todo: POSTPONED_ON(Aloha Editor, https://github.com/alohaeditor/Aloha-Editor/issues/693)
+ * Get rid of this helper function and move it into _initialize() once that
+ * issue is solved. Also see http://drupal.org/node/1725032.
+ */
+ _bindEvents: function() {
+ var that = this;
+
+ // Sets the state to 'activated' upon clicking the element.
+ this.element.on("click.edit", function(event) {
+ event.stopPropagation();
+ event.preventDefault();
+ that.options.activating();
+ });
+
+ // Sets the state to 'changed' whenever the content has changed.
+ this.element.on('aloha-content-changed', function(event, $alohaEditable, data) {
+ if (!data.editable.isModified()) {
+ return true;
+ }
+ that.options.changed(data.editable.getContents());
+ data.editable.setUnmodified();
+ });
+ },
+
+ /**
+ * Makes this PropertyEditor widget react to state changes.
+ */
+ stateChange: function(from, to) {
+ switch (to) {
+ case 'inactive':
+ break;
+ case 'candidate':
+ if (from !== 'inactive') {
+ Drupal.aloha.detach(this.element);
+ this._removeValidationErrors();
+ this._cleanUp();
+ this._bindEvents();
+ }
+ break;
+ case 'highlighted':
+ break;
+ case 'activating':
+ // When transformation filters have been been applied to the processed
+ // text of this field, then we'll need to load a re-rendered version of
+ // it without the transformation filters.
+ if (this.options.widget.element.hasClass('edit-text-with-transformation-filters')) {
+ this.originalTransformedContent = this.element.html();
+
+ var that = this;
+ Drupal.edit.util.loadRerenderedProcessedText({
+ $editorElement: this.element,
+ propertyID: Drupal.edit.util.calcPropertyID(this.options.entity, this.options.property),
+ callback: function (rerendered) {
+ that.element.html(rerendered);
+ that.options.activated();
+ }
+ });
+ }
+ // When no transformation filters have been applied: start WYSIWYG
+ // editing immediately!
+ else {
+ this.options.activated();
+ }
+ break;
+ case 'active':
+ // Attach Aloha Editor with this field's text format.
+ var formatID = this.options.widget.element.attr('data-edit-text-format');
+ var format = drupalSettings.aloha.formats[formatID];
+ // Let the custom Aloha Editor UI for Drupal know that it should
+ // render the Aloha Editor toolbar into Edit's toolbar.
+ this.element.attr('data-edit-aloha-toolbar-custom-location', 'true');
+ Drupal.aloha.attach(this.element, format);
+ Drupal.aloha.activate(this.element, format);
+ break;
+ case 'changed':
+ break;
+ case 'saving':
+ this._removeValidationErrors();
+ break;
+ case 'saved':
+ break;
+ case 'invalid':
+ break;
+ }
+ },
+
+ /**
+ * Removes validation errors' markup changes, if any.
+ *
+ * Note: this only needs to happen for type=direct, because for type=direct,
+ * the property DOM element itself is modified; this is not the case for
+ * type=form.
+ */
+ _removeValidationErrors: function() {
+ this.element
+ .removeClass('edit-validation-error')
+ .next('.edit-validation-errors').remove();
+ },
+
+ /**
+ * Cleans up after the widget has been saved.
+ *
+ * Note: this is where the Create.Storage and accompanying Backbone.sync
+ * abstractions "leak" implementation details. That is only the case because
+ * we have to use Drupal's Form API as a transport mechanism. It is
+ * unfortunately a stateful transport mechanism, and that's why we have to
+ * clean it up here. This clean-up is only necessary when canceling the
+ * editing of a property after having attempted to save at least once.
+ */
+ _cleanUp: function() {
+ Drupal.edit.util.form.unajaxifySaving(jQuery('#edit_backstage form .edit-form-submit'));
+ jQuery('#edit_backstage form').remove();
+ }
+ });
+
+})(jQuery, Drupal, drupalSettings);
diff --git a/edit_aloha/lib/Drupal/edit_aloha/Plugin/edit/processed_text_editor/Aloha.php b/edit_aloha/lib/Drupal/edit_aloha/Plugin/edit/processed_text_editor/Aloha.php
new file mode 100644
index 0000000..41474c1
--- /dev/null
+++ b/edit_aloha/lib/Drupal/edit_aloha/Plugin/edit/processed_text_editor/Aloha.php
@@ -0,0 +1,43 @@
+ $EDIT_DIR/$FILENAME-$COMMENTNR.patch
diff --git a/grunt.js b/grunt.js
index f160df9..d4398dd 100644
--- a/grunt.js
+++ b/grunt.js
@@ -43,10 +43,11 @@ module.exports = function(grunt) {
},
globals: {
jQuery: true,
+ _: true,
Backbone: true,
- Drupal: true,
VIE: true,
- _: true
+ Drupal: true,
+ drupalSettings: true
}
},
csslint: {
diff --git a/includes/pages.inc b/includes/pages.inc
index d29e87b..10b682d 100644
--- a/includes/pages.inc
+++ b/includes/pages.inc
@@ -4,6 +4,11 @@
* AJAX endpoints to retrieve & save subforms for fields and re-render fields.
*/
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\edit\Ajax\FieldFormCommand;
+use Drupal\edit\Ajax\FieldFormSavedCommand;
+use Drupal\edit\Ajax\FieldFormValidationErrorsCommand;
+use Drupal\edit\Ajax\FieldRenderedWithoutTransformationFiltersCommand;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -24,6 +29,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* A render array.
*/
function edit_field_edit($entity_type, $entity_id, $field_name, $langcode, $view_mode) {
+ $response = new AjaxResponse();
+
// Ensure the entity type is valid.
if (empty($entity_type)) {
throw new NotFoundHttpException();
@@ -64,39 +71,23 @@ function edit_field_edit($entity_type, $entity_id, $field_name, $langcode, $view
'no_redirect' => TRUE,
'build_info' => array('args' => array()),
);
- $commands = array();
form_load_include($form_state, 'inc', 'edit', 'includes/form');
$form = drupal_build_form('edit_field_form', $form_state);
- $id = "$entity_type:$entity_id:$field_name:$langcode:$view_mode";
if (!empty($form_state['executed'])) {
// Retrieve the updated entity, save it and render only the modified field.
$entity = $form_state['entity'];
$entity->save();
- $options = array('field_name' => $field_name);
- field_attach_prepare_view($entity->entityType(), array($entity->id() => $entity), $view_mode, $langcode, $options);
- $output = field_attach_view($entity->entityType(), $entity, $view_mode, $langcode, $options);
-
- $commands[] = array(
- 'command' => 'edit_field_form_saved',
- 'id' => $id,
- 'data' => drupal_render($output),
- );
+ $output = field_view_field($entity->entityType(), $entity, $field_name, $view_mode, $langcode);
+
+ $response->addCommand(new FieldFormSavedCommand(drupal_render($output)));
}
else {
- $commands[] = array(
- 'command' => 'edit_field_form',
- 'id' => $id,
- 'data' => drupal_render($form),
- );
+ $response->addCommand(new FieldFormCommand(drupal_render($form)));
$errors = form_get_errors();
if (count($errors)) {
- $commands[] = array(
- 'command' => 'edit_field_form_validation_errors',
- 'id' => $id,
- 'data' => theme('status_messages'),
- );
+ $response->addCommand(new FieldFormValidationErrorsCommand(theme('status_messages')));
}
}
@@ -106,7 +97,7 @@ function edit_field_edit($entity_type, $entity_id, $field_name, $langcode, $view
drupal_static_reset('drupal_add_js');
}
- return array('#type' => 'ajax', '#commands' => $commands);
+ return $response;
}
/**
@@ -129,6 +120,8 @@ function edit_field_edit($entity_type, $entity_id, $field_name, $langcode, $view
* A render array.
*/
function edit_text_field_render_without_transformation_filters($entity_type, $entity_id, $field_name, $langcode, $view_mode) {
+ $response = new AjaxResponse();
+
// Ensure the entity type is valid.
if (empty($entity_type)) {
throw new NotFoundHttpException();
@@ -162,18 +155,11 @@ function edit_text_field_render_without_transformation_filters($entity_type, $en
throw new NotFoundHttpException();
}
- $commands = array();
-
// Render the field in our custom display mode; retrieve the re-rendered
// markup, this is what we're after.
$field_output = field_view_field($entity_type, $entity, $field_name, 'edit-render-without-transformation-filters');
$output = $field_output[0]['#markup'];
+ $response->addCommand(new FieldRenderedWithoutTransformationFiltersCommand($output));
- $commands[] = array(
- 'command' => 'edit_field_rendered_without_transformation_filters',
- 'id' => "$entity_type:$entity_id:$field_name:$langcode:$view_mode",
- 'data' => $output,
- );
-
- return array('#type' => 'ajax', '#commands' => $commands);
+ return $response;
}
diff --git a/js/app.js b/js/app.js
index 82d390f..c5d5be5 100644
--- a/js/app.js
+++ b/js/app.js
@@ -308,7 +308,7 @@
// @todo: BLOCKED_ON(Create.js, https://github.com/bergie/create/issues/133)
// Get rid of this once that issue is solved.
- editor.options.widget.element.bind('createeditablestatechange', function(event, data) {
+ editor.options.widget.element.on('createeditablestatechange', function(event, data) {
editor.decorationView.stateChange(data.previous, data.current);
editor.toolbarView.stateChange(data.previous, data.current);
});
diff --git a/js/backbone.drupalform.js b/js/backbone.drupalform.js
index aee82c1..cc0e5c3 100644
--- a/js/backbone.drupalform.js
+++ b/js/backbone.drupalform.js
@@ -37,7 +37,7 @@ Backbone.syncDrupalFormWidget = function(method, model, options) {
var base = $submit.attr('id');
// Successfully saved.
- Drupal.ajax[base].commands.edit_field_form_saved = function(ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldFormSaved = function(ajax, response, status) {
Drupal.edit.util.form.unajaxifySaving(jQuery(ajax.element));
// Call Backbone.sync's success callback with the rerendered field.
@@ -51,7 +51,7 @@ Backbone.syncDrupalFormWidget = function(method, model, options) {
};
// Unsuccessfully saved; validation errors.
- Drupal.ajax[base].commands.edit_field_form_validation_errors = function(ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldFormValidationErrors = function(ajax, response, status) {
// Call Backbone.sync's error callback with the validation error messages.
options.error(response.data);
};
@@ -61,7 +61,7 @@ Backbone.syncDrupalFormWidget = function(method, model, options) {
// API then marks which form items have errors. Therefor, we have to replace
// the existing form, unbind the existing Drupal.ajax instance and create a
// new Drupal.ajax instance.
- Drupal.ajax[base].commands.edit_field_form = function(ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldForm = function(ajax, response, status) {
Drupal.edit.util.form.unajaxifySaving(jQuery(ajax.element));
Drupal.ajax.prototype.commands.insert(ajax, {
@@ -122,7 +122,7 @@ Backbone.syncDirect = function(method, model, options) {
var base = Drupal.edit.util.form.ajaxifySaving(formOptions, $submit);
// Successfully saved.
- Drupal.ajax[base].commands.edit_field_form_saved = function (ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldFormSaved = function (ajax, response, status) {
Drupal.edit.util.form.unajaxifySaving(jQuery(ajax.element));
jQuery('#edit_backstage form').remove();
@@ -130,18 +130,18 @@ Backbone.syncDirect = function(method, model, options) {
};
// Unsuccessfully saved; validation errors.
- Drupal.ajax[base].commands.edit_field_form_validation_errors = function(ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldFormValidationErrors = function(ajax, response, status) {
// Call Backbone.sync's error callback with the validation error messages.
options.error(response.data);
};
- // The edit_field_form AJAX command is only called upon loading the form
+ // The editFieldForm AJAX command is only called upon loading the form
// for the first time, and when there are validation errors in the form;
// Form API then marks which form items have errors. This is useful for
// "form" editors, but pointless for "direct" editors: the form itself
// won't be visible at all anyway! Therefor, we ignore the new form and
// we continue to use the existing form.
- Drupal.ajax[base].commands.edit_field_form = function(ajax, response, status) {
+ Drupal.ajax[base].commands.editFieldForm = function(ajax, response, status) {
// no-op
};
diff --git a/js/createjs/editable.js b/js/createjs/editable.js
index cc34498..aac1ed2 100644
--- a/js/createjs/editable.js
+++ b/js/createjs/editable.js
@@ -2,12 +2,12 @@
* @file
* Determines which editor to use based on a class attribute.
*/
-(function (jQuery, Drupal) {
+(function (jQuery, drupalSettings) {
"use strict";
jQuery.widget('Drupal.createEditable', jQuery.Midgard.midgardEditable, {
- _create: function () {
+ _create: function() {
this.vie = this.options.vie;
this.options.domService = 'edit';
@@ -18,7 +18,7 @@
options: {}
};
this.options.editors['direct-with-wysiwyg'] = {
- widget: 'drupalAlohaWidget',
+ widget: drupalSettings.edit.wysiwygEditorWidgetName,
options: {}
};
this.options.editors.form = {
@@ -29,8 +29,8 @@
jQuery.Midgard.midgardEditable.prototype._create.call(this);
},
- _propertyEditorName: function (data) {
- if (Drupal.settings.edit.wysiwyg && jQuery(this.element).hasClass('edit-type-direct')) {
+ _propertyEditorName: function(data) {
+ if (jQuery(this.element).hasClass('edit-type-direct')) {
if (jQuery(this.element).hasClass('edit-type-direct-with-wysiwyg')) {
return 'direct-with-wysiwyg';
}
@@ -40,4 +40,4 @@
}
});
-})(jQuery, Drupal);
+})(jQuery, drupalSettings);
diff --git a/js/createjs/editingWidgets/drupalalohawidget.js b/js/createjs/editingWidgets/drupalalohawidget.js
deleted file mode 100644
index 6ef3a93..0000000
--- a/js/createjs/editingWidgets/drupalalohawidget.js
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * @file
- * Override of Create.js' default Aloha Editor widget.
- *
- * NOTE: This does in fact use zero code of jQuery.create.alohaWidget.
- */
-(function (jQuery, Drupal) {
-
-"use strict";
-
- jQuery.widget('Drupal.drupalAlohaWidget', jQuery.Create.alohaWidget, {
-
- // @todo BLOCKED_ON(Create.js/VIE.js, how to restore original content when canceling editing)
- // Actually use this when restoring original content, but for that we
- // first need to know how to restore content in a Create.js context
- originalTransformedContent: null,
-
- /**
- * Implements jQuery UI widget factory's _init() method.
- *
- * @todo: POSTPONED_ON(Create.js, https://github.com/bergie/create/issues/142)
- * Get rid of this once that issue is solved.
- */
- _init: function() {},
-
- /**
- * Implements Create's _initialize() method.
- */
- _initialize: function() {
- this._bindEvents();
-
- // Immediately initialize Aloha, this can take some time. By doing it now
- // already, it will most likely already be ready when the user actually
- // wants to use Aloha Editor.
- Drupal.aloha.init();
- },
-
- /**
- * Binds to events.
- *
- * @todo: POSTPONED_ON(Aloha Editor, https://github.com/alohaeditor/Aloha-Editor/issues/693)
- * Get rid of this helper function and move it into _initialize() once that
- * issue is solved. Also see http://drupal.org/node/1725032.
- */
- _bindEvents: function() {
- var that = this;
-
- // Sets the state to 'activated' upon clicking the element.
- this.element.bind("click.edit", function(event) {
- event.stopPropagation();
- event.preventDefault();
- that.options.activating();
- });
-
- // Sets the state to 'changed' whenever the content has changed.
- this.element.bind('aloha-content-changed', function(event, $alohaEditable, data) {
- if (!data.editable.isModified()) {
- return true;
- }
- that.options.changed(data.editable.getContents());
- data.editable.setUnmodified();
- });
- },
-
- /**
- * Makes this PropertyEditor widget react to state changes.
- */
- stateChange: function(from, to) {
- switch (to) {
- case 'inactive':
- break;
- case 'candidate':
- if (from !== 'inactive') {
- Drupal.aloha.detach(this.element);
- this._removeValidationErrors();
- this._cleanUp();
- this._bindEvents();
- }
- break;
- case 'highlighted':
- break;
- case 'activating':
- // When transformation filters have been been applied to the processed
- // text of this field, then we'll need to load a re-rendered version of
- // it without the transformation filters.
- if (this.options.widget.element.hasClass('edit-text-with-transformation-filters')) {
- this.originalTransformedContent = this.element.html();
-
- var that = this;
- Drupal.edit.util.loadRerenderedProcessedText({
- $editorElement: this.element,
- propertyID: Drupal.edit.util.calcPropertyID(this.options.entity, this.options.property),
- callback: function (rerendered) {
- that.element.html(rerendered);
- that.options.activated();
- }
- });
- }
- // When no transformation filters have been applied: start WYSIWYG
- // editing immediately!
- else {
- this.options.activated();
- }
- break;
- case 'active':
- // Attach Aloha Editor with this field's text format.
- var formatID = this.options.widget.element.attr('data-edit-text-format');
- var format = Drupal.settings.aloha.formats[formatID];
- Drupal.aloha.attach(this.element, format);
- Drupal.aloha.activate(this.element, format);
- break;
- case 'changed':
- break;
- case 'saving':
- this._removeValidationErrors();
- break;
- case 'saved':
- break;
- case 'invalid':
- break;
- }
- },
-
- /**
- * Removes validation errors' markup changes, if any.
- *
- * Note: this only needs to happen for type=direct, because for type=direct,
- * the property DOM element itself is modified; this is not the case for
- * type=form.
- */
- _removeValidationErrors: function() {
- this.element
- .removeClass('edit-validation-error')
- .next('.edit-validation-errors').remove();
- },
-
- /**
- * Cleans up after the widget has been saved.
- *
- * Note: this is where the Create.Storage and accompanying Backbone.sync
- * abstractions "leak" implementation details. That is only the case because
- * we have to use Drupal's Form API as a transport mechanism. It is
- * unfortunately a stateful transport mechanism, and that's why we have to
- * clean it up here. This clean-up is only necessary when canceling the
- * editing of a property after having attempted to save at least once.
- */
- _cleanUp: function() {
- Drupal.edit.util.form.unajaxifySaving(jQuery('#edit_backstage form .edit-form-submit'));
- jQuery('#edit_backstage form').remove();
- }
- });
-
-})(jQuery, Drupal);
diff --git a/js/createjs/editingWidgets/drupalcontenteditablewidget.js b/js/createjs/editingWidgets/drupalcontenteditablewidget.js
index 65f5116..c773e6e 100644
--- a/js/createjs/editingWidgets/drupalcontenteditablewidget.js
+++ b/js/createjs/editingWidgets/drupalcontenteditablewidget.js
@@ -23,7 +23,7 @@
var that = this;
// Sets the state to 'activated' upon clicking the element.
- this.element.bind("click.edit", function(event) {
+ this.element.on("click.edit", function(event) {
event.stopPropagation();
event.preventDefault();
that.options.activated();
@@ -31,7 +31,7 @@
// Sets the state to 'changed' whenever the content has changed.
var before = jQuery.trim(this.element.text());
- this.element.bind('keyup paste', function (event) {
+ this.element.on('keyup paste', function (event) {
if (that.options.disabled) {
return;
}
diff --git a/js/createjs/editingWidgets/formwidget.js b/js/createjs/editingWidgets/formwidget.js
index 889ee87..9a5153d 100644
--- a/js/createjs/editingWidgets/formwidget.js
+++ b/js/createjs/editingWidgets/formwidget.js
@@ -25,7 +25,7 @@
_initialize: function() {
// Sets the state to 'activating' upon clicking the element.
var that = this;
- this.element.bind("click.edit", function(event) {
+ this.element.on("click.edit", function(event) {
event.stopPropagation();
event.preventDefault();
that.options.activating();
@@ -114,11 +114,11 @@
var $submit = widget.$formContainer.find('.edit-form-submit');
Drupal.edit.util.form.ajaxifySaving(formOptions, $submit);
widget.$formContainer
- .delegate(':input', 'formUpdated.edit', function () {
+ .on('formUpdated.edit', ':input', function () {
// Sets the state to 'changed'.
widget.options.changed();
})
- .delegate('input', 'keypress.edit', function (event) {
+ .on('keypress.edit', 'input', function (event) {
if (event.keyCode === 13) {
return false;
}
@@ -139,8 +139,8 @@
Drupal.edit.util.form.unajaxifySaving(this.$formContainer.find('.edit-form-submit'));
this.$formContainer
- .undelegate(':input', 'change.edit')
- .undelegate('input', 'keypress.edit')
+ .off('change.edit', ':input')
+ .off('keypress.edit', 'input')
.remove();
this.$formContainer = null;
}
diff --git a/js/edit.js b/js/edit.js
index 0c813fb..2c42068 100644
--- a/js/edit.js
+++ b/js/edit.js
@@ -25,6 +25,12 @@ Drupal.behaviors.editDiscoverEditables = {
Drupal.behaviors.edit = {
attach: function(context) {
$('#edit_view-edit-toggles').once('edit-init', Drupal.edit.init);
+
+ // As soon as there is at least one editable field, show the Edit tab in the
+ // toolbar.
+ if ($(context).find('.edit-field.edit-allowed').length) {
+ $('.toolbar .icon-edit.edit-nothing-editable-hidden').removeClass('edit-nothing-editable-hidden');
+ }
}
};
diff --git a/js/util.js b/js/util.js
index 6b0044b..8ed9a2b 100644
--- a/js/util.js
+++ b/js/util.js
@@ -2,7 +2,7 @@
* @file
* Provides utility functions for Edit.
*/
-(function($, Drupal) {
+(function($, Drupal, drupalSettings) {
"use strict";
@@ -44,19 +44,21 @@ Drupal.edit.util.buildUrl = function(id, urlFormat) {
Drupal.edit.util.loadRerenderedProcessedText = function(options) {
// Create a Drupal.ajax instance to load the form.
Drupal.ajax[options.propertyID] = new Drupal.ajax(options.propertyID, options.$editorElement, {
- url: Drupal.edit.util.buildUrl(options.propertyID, Drupal.settings.edit.rerenderProcessedTextURL),
+ url: Drupal.edit.util.buildUrl(options.propertyID, drupalSettings.edit.rerenderProcessedTextURL),
event: 'edit-internal.edit',
submit: { nocssjs : true },
progress: { type : null } // No progress indicator.
});
- // Implement a scoped edit_field_form AJAX command: calls the callback.
- Drupal.ajax[options.propertyID].commands.edit_field_rendered_without_transformation_filters = function(ajax, response, status) {
+ // Implement a scoped editFieldRenderedWithoutTransformationFilters AJAX
+ // command: calls the callback.
+ Drupal.ajax[options.propertyID].commands.editFieldRenderedWithoutTransformationFilters = function(ajax, response, status) {
options.callback(response.data);
// Delete the Drupal.ajax instance that called this very function.
delete Drupal.ajax[options.propertyID];
- options.$editorElement.unbind('edit-internal.edit');
+ options.$editorElement.off('edit-internal.edit');
};
- // This will ensure our scoped edit_field_form AJAX command gets called.
+ // This will ensure our scoped editFieldRenderedWithoutTransformationFilters
+ // AJAX command gets called.
options.$editorElement.trigger('edit-internal.edit');
};
@@ -82,19 +84,19 @@ Drupal.edit.util.form = {
load: function(options, callback) {
// Create a Drupal.ajax instance to load the form.
Drupal.ajax[options.propertyID] = new Drupal.ajax(options.propertyID, options.$editorElement, {
- url: Drupal.edit.util.buildUrl(options.propertyID, Drupal.settings.edit.fieldFormURL),
+ url: Drupal.edit.util.buildUrl(options.propertyID, drupalSettings.edit.fieldFormURL),
event: 'edit-internal.edit',
submit: { nocssjs : options.nocssjs },
progress: { type : null } // No progress indicator.
});
- // Implement a scoped edit_field_form AJAX command: calls the callback.
- Drupal.ajax[options.propertyID].commands.edit_field_form = function(ajax, response, status) {
+ // Implement a scoped editFieldForm AJAX command: calls the callback.
+ Drupal.ajax[options.propertyID].commands.editFieldForm = function(ajax, response, status) {
callback(response.data, ajax);
// Delete the Drupal.ajax instance that called this very function.
delete Drupal.ajax[options.propertyID];
- options.$editorElement.unbind('edit-internal.edit');
+ options.$editorElement.off('edit-internal.edit');
};
- // This will ensure our scoped edit_field_form AJAX command gets called.
+ // This will ensure our scoped editFieldForm AJAX command gets called.
options.$editorElement.trigger('edit-internal.edit');
},
@@ -133,8 +135,8 @@ Drupal.edit.util.form = {
*/
unajaxifySaving: function($submit) {
delete Drupal.ajax[$submit.attr('id')];
- $submit.unbind('click.edit');
+ $submit.off('click.edit');
}
};
-})(jQuery, Drupal);
+})(jQuery, Drupal, drupalSettings);
diff --git a/js/viejs/EditService.js b/js/viejs/EditService.js
index cde0e2e..5545463 100644
--- a/js/viejs/EditService.js
+++ b/js/viejs/EditService.js
@@ -2,7 +2,7 @@
* @file
* VIE DOM parsing service for Edit.
*/
-(function(jQuery, _, Drupal, VIE) {
+(function(jQuery, _, VIE, Drupal, drupalSettings) {
"use strict";
@@ -30,7 +30,7 @@
if (typeof document === 'undefined') {
return loadable.resolve([]);
} else {
- element = Drupal.settings.edit.context;
+ element = drupalSettings.edit.context;
}
} else {
element = loadable.options.element;
@@ -170,7 +170,7 @@
// editable fields.
findSubjectElements: function (element) {
if (!element) {
- element = Drupal.settings.edit.context;
+ element = drupalSettings.edit.context;
}
return jQuery(this.options.subjectSelector, element);
},
@@ -198,4 +198,4 @@
}
};
-})(jQuery, _, Drupal, VIE);
+})(jQuery, _, VIE, Drupal, drupalSettings);
diff --git a/js/views/modal-view.js b/js/views/modal-view.js
index 0f3c0aa..c5d91ab 100644
--- a/js/views/modal-view.js
+++ b/js/views/modal-view.js
@@ -85,7 +85,7 @@ Drupal.edit.views.ModalView = Backbone.View.extend({
var that = this;
this.$el
.addClass('edit-animate-invisible')
- .bind(Drupal.edit.util.constants.transitionEnd, function(e) {
+ .on(Drupal.edit.util.constants.transitionEnd, function(e) {
that.remove();
});
diff --git a/js/views/overlay-view.js b/js/views/overlay-view.js
index e545087..e357014 100644
--- a/js/views/overlay-view.js
+++ b/js/views/overlay-view.js
@@ -73,7 +73,7 @@ Drupal.edit.views.OverlayView = Backbone.View.extend({
var that = this;
this.$el
.addClass('edit-animate-invisible')
- .bind(Drupal.edit.util.constants.transitionEnd, function (event) {
+ .on(Drupal.edit.util.constants.transitionEnd, function (event) {
that.$el.remove();
});
}
diff --git a/js/views/toolbar-view.js b/js/views/toolbar-view.js
index c31791a..4b8235c 100644
--- a/js/views/toolbar-view.js
+++ b/js/views/toolbar-view.js
@@ -384,7 +384,7 @@ Drupal.edit.views.ToolbarView = Backbone.View.extend({
.removeAttr('id')
.find('.edit-toolbar .edit-toolgroup')
.addClass('edit-animate-invisible')
- .bind(Drupal.edit.util.constants.transitionEnd, function (e) {
+ .on(Drupal.edit.util.constants.transitionEnd, function (e) {
$el.remove();
});
},
diff --git a/lib/Drupal/edit/Ajax/BaseCommand.php b/lib/Drupal/edit/Ajax/BaseCommand.php
new file mode 100644
index 0000000..32d325d
--- /dev/null
+++ b/lib/Drupal/edit/Ajax/BaseCommand.php
@@ -0,0 +1,52 @@
+command = $command;
+ $this->data = $data;
+ }
+
+ /**
+ * Implements Drupal\Core\Ajax\CommandInterface:render().
+ */
+ public function render() {
+ return array(
+ 'command' => $this->command,
+ 'data' => $this->data,
+ );
+ }
+
+}
diff --git a/lib/Drupal/edit/Ajax/FieldFormCommand.php b/lib/Drupal/edit/Ajax/FieldFormCommand.php
new file mode 100644
index 0000000..76b01c5
--- /dev/null
+++ b/lib/Drupal/edit/Ajax/FieldFormCommand.php
@@ -0,0 +1,27 @@
+register('plugin.manager.edit.processed_text_editor', 'Drupal\edit\Plugin\Type\ProcessedTextEditorManager');
+ }
+
+}
diff --git a/lib/Drupal/edit/Plugin/ProcessedTextEditorBase.php b/lib/Drupal/edit/Plugin/ProcessedTextEditorBase.php
new file mode 100644
index 0000000..41c0141
--- /dev/null
+++ b/lib/Drupal/edit/Plugin/ProcessedTextEditorBase.php
@@ -0,0 +1,35 @@
+discovery = new AnnotatedClassDiscovery('edit', 'processed_text_editor');
+ $this->discovery = new AlterDecorator($this->discovery, 'edit_wysiwyg');
+ $this->discovery = new CacheDecorator($this->discovery, 'edit:wysiwyg');
+ $this->factory = new DefaultFactory($this->discovery);
+ }
+
+}
diff --git a/lib/Drupal/edit/Tests/FieldEditorTest.php b/lib/Drupal/edit/Tests/FieldEditorTest.php
new file mode 100644
index 0000000..0763c68
--- /dev/null
+++ b/lib/Drupal/edit/Tests/FieldEditorTest.php
@@ -0,0 +1,149 @@
+ 'Field editor selection',
+ 'description' => 'Tests field editor selection.',
+ 'group' => 'Edit',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ $filtered_html_format = filter_format_load('filtered_html');
+ $this->admin_user = $this->drupalCreateUser(array(
+ 'administer filters',
+ 'administer nodes',
+ 'bypass node access',
+ filter_permission_name($filtered_html_format),
+ ));
+ $this->drupalLogin($this->admin_user);
+
+ // Add test text field.
+ $field_name = 'field_test_edit_text_test';
+ $field = array(
+ 'field_name' => $field_name,
+ 'type' => 'text',
+ 'cardinality' => 1,
+ );
+ field_create_field($field);
+ $instance = array(
+ 'entity_type' => 'node',
+ 'field_name' => $field_name,
+ 'bundle' => 'article',
+ 'label' => 'Test text-field',
+ 'widget' => array(
+ 'type' => 'text_textfield',
+ 'weight' => 0,
+ ),
+ 'default_value' => array('Default text'),
+ );
+ field_create_instance($instance);
+
+ // Add test number field.
+ $field_name = 'field_test_edit_number_test';
+ $field = array(
+ 'field_name' => $field_name,
+ 'type' => 'number_decimal',
+ 'cardinality' => 1,
+ 'settings' => array(
+ 'precision' => 8, 'scale' => 4, 'decimal_separator' => '.',
+ )
+ );
+ field_create_field($field);
+ $instance = array(
+ 'field_name' => $field_name,
+ 'entity_type' => 'node',
+ 'label' => 'Test number field',
+ 'bundle' => 'article',
+ 'widget' => array(
+ 'type' => 'number',
+ ),
+ 'display' => array(
+ 'default' => array(
+ 'type' => 'number_decimal',
+ ),
+ ),
+ 'default_value' => array('12.4'),
+ );
+ field_create_instance($instance);
+
+ // Create an article node.
+ $this->node = $this->drupalCreateNode(array('type' => 'article'));
+ }
+
+ function testContent() {
+ $default_edit = 'edit-field edit-allowed edit-type-form';
+ $fields = array(
+ 'body' => $default_edit,
+ 'field_test_edit_number_test' => $default_edit,
+ // Edit fields are directly editable, see edit.patch.
+ 'field_test_edit_text_test' => 'edit-field edit-allowed edit-type-direct',
+ );
+
+ // Test editability with fields on the node.
+ foreach ($fields as $field_name => $assert) {
+ $field_view = field_view_field('node', $this->node, $field_name);
+ $content = drupal_render($field_view);
+ $this->drupalSetContent($content);
+ $this->assertRaw($assert);
+ }
+
+ // Turn off filters that are incompatible with in place editing.
+ // Add p and br as allowed tags.
+ $edit = array(
+ 'filters[filter_url][status]' => FALSE,
+ 'filters[filter_autop][status]' => FALSE,
+ 'filters[filter_html][settings][allowed_html]' => ' -
-
-
',
+ );
+ $this->drupalPost('admin/config/content/formats/filtered_html', $edit, t('Save configuration'));
+
+ // @todo: this should not pass yet.
+
+ // Test editability with fields on the node.
+ foreach ($fields as $field_name => $assert) {
+ $field_view = field_view_field('node', $this->node, $field_name);
+ $content = drupal_render($field_view);
+ $this->drupalSetContent($content);
+ $this->assertRaw($assert);
+ }
+
+ }
+}
diff --git a/text.patch b/text.patch
index 83dcd75..d60f5df 100644
--- a/text.patch
+++ b/text.patch
@@ -14,7 +14,7 @@ index 6b34ba9..85d2878 100644
* "text_with_summary"
+ * },
+ * edit = {
-+ * "editability" = "direct"
++ * "editor" = "direct"
* }
* )
*/
@@ -28,7 +28,7 @@ index 0f7b615..8dc4bf1 100644
* "text_with_summary"
+ * },
+ * edit = {
-+ * "editability" = "direct"
++ * "editor" = "direct"
* }
* )
*/
@@ -42,7 +42,7 @@ index 11f0c14..c69e5e0 100644
* "trim_length" = "600"
+ * },
+ * edit = {
-+ * "editability" = "form"
++ * "editor" = "form"
* }
* )
*/
@@ -56,7 +56,7 @@ index 349cf63..add5d55 100644
* "trim_length" = "600"
+ * },
+ * edit = {
-+ * "editability" = "form"
++ * "editor" = "form"
* }
* )
*/