diff --git a/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php
index 7e31231..377bf4a 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php
@@ -45,6 +45,16 @@ class AnnotatedClassDiscovery implements DiscoveryInterface {
 
   /**
    * Constructs an AnnotatedClassDiscovery object.
+   *
+   * @param array $plugin_namespaces
+   *   (optional) An array of namespace that may contain plugin implementations.
+   *   Defaults to an empty array.
+   * @param array $annotation_namespaces
+   *   (optional) The namespaces of classes that can be used as annotations.
+   *   Defaults to an empty array.
+   * @param string $plugin_definition_annotation_name
+   *   (optional) The name of the annotation that contains the plugin definition.
+   *   Defaults to 'Drupal\Component\Annotation\Plugin'.
    */
   function __construct($plugin_namespaces = array(), $annotation_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') {
     $this->pluginNamespaces = $plugin_namespaces;
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php
index 3c10366..8ed9440 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php
@@ -22,9 +22,15 @@ class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery {
    * @param string $type
    *   The plugin type, for example filter.
    * @param array $root_namespaces
-   *   Array of root paths keyed by the corresponding namespace to look for
-   *   plugin implementations, \Plugin\$owner\$type will be appended to each
-   *   namespace.
+   *   (optional) An array of root paths keyed by the corresponding namespace to
+   *   look for plugin implementations. '\Plugin\$owner\$type' will be appended
+   *   to each namespace. Defaults to an empty array.
+   * @param array $annotation_namespaces
+   *   (optional) The namespaces of classes that can be used as annotations.
+   *   Defaults to an empty array.
+   * @param string $plugin_definition_annotation_name
+   *   (optional) The name of the annotation that contains the plugin definition.
+   *   Defaults to 'Drupal\Component\Annotation\Plugin'.
    *
    * @todo Figure out how to make the following comment FALSE.
    *   Drupal modules can be enabled (and therefore, namespaces registered)
@@ -33,8 +39,8 @@ class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery {
    *   until the next request. Additionally when a namespace is unregistered,
    *   plugins will not be removed until the next request.
    */
-  function __construct($owner, $type, array $root_namespaces = array()) {
-    $annotation_namespaces = array(
+  function __construct($owner, $type, array $root_namespaces = array(), $annotation_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') {
+    $annotation_namespaces += array(
       'Drupal\Component\Annotation' => DRUPAL_ROOT . '/core/lib',
       'Drupal\Core\Annotation' => DRUPAL_ROOT . '/core/lib',
     );
@@ -42,7 +48,7 @@ function __construct($owner, $type, array $root_namespaces = array()) {
     foreach ($root_namespaces as $namespace => $dir) {
       $plugin_namespaces["$namespace\\Plugin\\{$owner}\\{$type}"] = array($dir);
     }
-    parent::__construct($plugin_namespaces, $annotation_namespaces);
+    parent::__construct($plugin_namespaces, $annotation_namespaces, $plugin_definition_annotation_name);
   }
 
 }
diff --git a/core/modules/ban/ban.admin.inc b/core/modules/ban/ban.admin.inc
deleted file mode 100644
index 9f20a45..0000000
--- a/core/modules/ban/ban.admin.inc
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-/**
- * @file
- * Administrative functionality for the Ban module.
- */
-
-/**
- * Page callback: Displays banned IP addresses.
- *
- * @param string $default_ip
- *   (optional) IP address to be passed on to drupal_get_form() for use as the
- *   default value of the IP address form field.
- *
- * @return array
- *   A render array.
- */
-function ban_admin_page($default_ip = '') {
-  $rows = array();
-  $header = array(t('banned IP addresses'), t('Operations'));
-  $result = db_query('SELECT * FROM {ban_ip}');
-  foreach ($result as $ip) {
-    $row = array();
-    $row[] = $ip->ip;
-    $links = array();
-    $links['delete'] = array(
-      'title' => t('delete'),
-      'href' => "admin/config/people/ban/delete/$ip->iid",
-    );
-    $row[] = array(
-      'data' => array(
-        '#type' => 'operations',
-        '#links' => $links,
-      ),
-    );
-    $rows[] = $row;
-  }
-
-  $build['ban_ip_form'] = drupal_get_form('ban_ip_form', $default_ip);
-
-  $build['ban_ip_banning_table'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $rows,
-    '#empty' => t('No blocked IP addresses available.'),
-  );
-
-  return $build;
-}
-
-/**
- * Form constructor for banning an IP address.
- *
- * @param string $default_ip
- *   An IP address to ban, used as default value.
- *
- * @see ban_ip_form_validate()
- * @see ban_ip_form_submit()
- * @ingroup forms
- */
-function ban_ip_form($form, &$form_state, $default_ip) {
-  $form['ip'] = array(
-    '#title' => t('IP address'),
-    '#type' => 'textfield',
-    '#size' => 48,
-    '#maxlength' => 40,
-    '#default_value' => $default_ip,
-    '#description' => t('Enter a valid IP address.'),
-  );
-  $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add'),
-  );
-  return $form;
-}
-
-/**
- * Form validation handler for ban_ip_form().
- *
- * @see ban_ip_form_submit()
- */
-function ban_ip_form_validate($form, &$form_state) {
-  $ip = trim($form_state['values']['ip']);
-  if (db_query("SELECT * FROM {ban_ip} WHERE ip = :ip", array(':ip' => $ip))->fetchField()) {
-    form_set_error('ip', t('This IP address is already banned.'));
-  }
-  elseif ($ip == Drupal::request()->getClientIP()) {
-    form_set_error('ip', t('You may not ban your own IP address.'));
-  }
-  elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) == FALSE) {
-    form_set_error('ip', t('Enter a valid IP address.'));
-  }
-}
-
-/**
- * Form submission handler for ban_ip_form().
- *
- * @see ban_ip_form_validate()
- */
-function ban_ip_form_submit($form, &$form_state) {
-  $ip = trim($form_state['values']['ip']);
-  db_insert('ban_ip')
-    ->fields(array('ip' => $ip))
-    ->execute();
-  drupal_set_message(t('The IP address %ip has been banned.', array('%ip' => $ip)));
-  $form_state['redirect'] = 'admin/config/people/ban';
-}
-
-/**
- * Form constructor to unban an IP address.
- *
- * @param array $ban_ip
- *   The IP address record to unban, as provided by ban_ip_load().
- *
- * @see ban_ip_delete_submit()
- */
-function ban_ip_delete_form($form, &$form_state, array $ban_ip) {
-  $form['ban_ip'] = array(
-    '#type' => 'value',
-    '#value' => $ban_ip,
-  );
-  return confirm_form($form,
-    t('Are you sure you want to unblock %ip?', array('%ip' => $ban_ip['ip'])),
-    'admin/config/people/ban',
-    NULL,
-    t('Delete')
-  );
-}
-
-/**
- * Form submission handler for ban_ip_delete_form().
- */
-function ban_ip_delete_form_submit($form, &$form_state) {
-  $banned_ip = $form_state['values']['ban_ip'];
-  db_delete('ban_ip')
-    ->condition('iid', $banned_ip['iid'])
-    ->execute();
-  watchdog('user', 'Deleted %ip', array('%ip' => $banned_ip['ip']));
-  drupal_set_message(t('The IP address %ip was deleted.', array('%ip' => $banned_ip['ip'])));
-  $form_state['redirect'] = 'admin/config/people/ban';
-}
diff --git a/core/modules/ban/ban.module b/core/modules/ban/ban.module
index 9e9ed0f..29becf5 100644
--- a/core/modules/ban/ban.module
+++ b/core/modules/ban/ban.module
@@ -44,30 +44,12 @@ function ban_menu() {
   $items['admin/config/people/ban'] = array(
     'title' => 'IP address bans',
     'description' => 'Manage banned IP addresses.',
-    'page callback' => 'ban_admin_page',
-    'access arguments' => array('ban IP addresses'),
-    'file' => 'ban.admin.inc',
+    'route_name' => 'ban_admin_page',
     'weight' => 10,
   );
   $items['admin/config/people/ban/delete/%ban_ip'] = array(
     'title' => 'Delete IP address',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('ban_ip_delete_form', 5),
-    'access arguments' => array('ban IP addresses'),
-    'file' => 'ban.admin.inc',
+    'route_name' => 'ban_delete',
   );
   return $items;
 }
-
-/**
- * Loads a banned IP address record from the database.
- *
- * @param int $iid
- *   The ID of the banned IP address to retrieve.
- *
- * @return array
- *   The banned IP address record from the database as an array.
- */
-function ban_ip_load($iid) {
-  return db_query("SELECT * FROM {ban_ip} WHERE iid = :iid", array(':iid' => $iid))->fetchAssoc();
-}
diff --git a/core/modules/ban/ban.routing.yml b/core/modules/ban/ban.routing.yml
new file mode 100644
index 0000000..366bd2e
--- /dev/null
+++ b/core/modules/ban/ban.routing.yml
@@ -0,0 +1,14 @@
+ban_admin_page:
+  pattern: '/admin/config/people/ban/{default_ip}'
+  defaults:
+    _form: '\Drupal\ban\Form\BanAdmin'
+    default_ip: ''
+  requirements:
+    _permission: 'ban IP addresses'
+
+ban_delete:
+  pattern: '/admin/config/people/ban/delete/{ban_ip}'
+  defaults:
+    _form: '\Drupal\ban\Form\BanDelete'
+  requirements:
+    _permission: 'ban IP addresses'
diff --git a/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php
new file mode 100644
index 0000000..b2cd013
--- /dev/null
+++ b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php
@@ -0,0 +1,145 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\ban\Form\BanAdmin.
+ */
+
+namespace Drupal\ban\Form;
+
+use Drupal\Core\Form\FormInterface;
+use Drupal\Core\ControllerInterface;
+use Drupal\Core\Database\Database;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Displays banned IP addresses.
+ */
+class BanAdmin implements FormInterface, ControllerInterface {
+
+  /**
+   * The request object.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * The database connection object.
+   *
+   * @var \Drupal\Core\Database\Database
+   */
+  protected $database;
+
+  /**
+   * Constructs a new BanAdmin object.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object.
+   * @param \Drupal\Core\Database\Database $database
+   *   The database connection object.
+   */
+  public function __construct(Request $request, Database $database) {
+    $this->request = $request;
+    $this->database = $database;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('request'),
+      $container->get('database')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'ban_ip_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param string $default_ip
+   *   (optional) IP address to be passed on to drupal_get_form() for use as the
+   *   default value of the IP address form field.
+   */
+  public function buildForm(array $form, array &$form_state, $default_ip = '') {
+    $rows = array();
+    $header = array(t('banned IP addresses'), t('Operations'));
+    $result = $this->database->query('SELECT * FROM {ban_ip}');
+    foreach ($result as $ip) {
+      $row = array();
+      $row[] = $ip->ip;
+      $links = array();
+      $links['delete'] = array(
+        'title' => t('delete'),
+        'href' => "admin/config/people/ban/delete/$ip->iid",
+      );
+      $row[] = array(
+        'data' => array(
+          '#type' => 'operations',
+          '#links' => $links,
+        ),
+      );
+      $rows[] = $row;
+    }
+
+    $form['ip'] = array(
+      '#title' => t('IP address'),
+      '#type' => 'textfield',
+      '#size' => 48,
+      '#maxlength' => 40,
+      '#default_value' => $default_ip,
+      '#description' => t('Enter a valid IP address.'),
+    );
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Add'),
+    );
+
+    $form['ban_ip_banning_table'] = array(
+      '#theme' => 'table',
+      '#header' => $header,
+      '#rows' => $rows,
+      '#empty' => t('No blocked IP addresses available.'),
+      '#weight' => 120,
+    );
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+    $ip = trim($form_state['values']['ip']);
+    if ($this->database->query("SELECT * FROM {ban_ip} WHERE ip = :ip", array(':ip' => $ip))->fetchField()) {
+      form_set_error('ip', t('This IP address is already banned.'));
+    }
+    elseif ($ip == $this->request->getClientIP()) {
+      form_set_error('ip', t('You may not ban your own IP address.'));
+    }
+    elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) == FALSE) {
+      form_set_error('ip', t('Enter a valid IP address.'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $ip = trim($form_state['values']['ip']);
+    $this->database->insert('ban_ip')
+      ->fields(array('ip' => $ip))
+      ->execute();
+    drupal_set_message(t('The IP address %ip has been banned.', array('%ip' => $ip)));
+    $form_state['redirect'] = 'admin/config/people/ban';
+  }
+
+}
diff --git a/core/modules/ban/lib/Drupal/ban/Form/BanDelete.php b/core/modules/ban/lib/Drupal/ban/Form/BanDelete.php
new file mode 100644
index 0000000..8017f9c
--- /dev/null
+++ b/core/modules/ban/lib/Drupal/ban/Form/BanDelete.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\ban\Form\BanDelete.
+ */
+
+namespace Drupal\ban\Form;
+
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\ControllerInterface;
+use Drupal\Core\Database\Database;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a form to unban IP addresses.
+ */
+class BanDelete extends ConfirmFormBase implements ControllerInterface {
+
+  /**
+   * The IP address information.
+   *
+   * @var array
+   */
+  protected $banIP = array();
+
+  /**
+   * The database connection object.
+   *
+   * @var \Drupal\Core\Database\Database
+   */
+  protected $database;
+
+  /**
+   * Constructs a new BanAdmin object.
+   *
+   * @param \Drupal\Core\Database\Database $database
+   *   The database connection object.
+   */
+  public function __construct(Database $database) {
+    $this->database = $database;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('database')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'ban_ip_delete_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getQuestion() {
+    return t('Are you sure you want to unblock %ip?', array('%ip' => $this->banIP['ip']));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getConfirmText() {
+    return t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getCancelPath() {
+    return 'admin/config/people/ban';
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param int $ban_ip_id
+   *   The IP address record ID to unban.
+   */
+  public function buildForm(array $form, array &$form_state, $ban_ip = '') {
+    $this->banIP = $this->database->query("SELECT * FROM {ban_ip} WHERE iid = :iid", array(':iid' => $ban_ip))->fetchAssoc();
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $this->database->delete('ban_ip')
+      ->condition('iid', $this->banIP['iid'])
+      ->execute();
+    watchdog('user', 'Deleted %ip', array('%ip' => $this->banIP['ip']));
+    drupal_set_message(t('The IP address %ip was deleted.', array('%ip' => $this->banIP['ip'])));
+    $form_state['redirect'] = 'admin/config/people/ban';
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php
new file mode 100644
index 0000000..792f8a7
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Plugin\Discovery\CustomAnnotationClassDiscoveryTest.
+ */
+
+namespace Drupal\system\Tests\Plugin\Discovery;
+
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+
+/**
+ * Tests that a custom annotation class is used.
+ *
+ * @see \Drupal\plugin_test\Plugin\Annotation\PluginExample
+ */
+class CustomAnnotationClassDiscoveryTest extends DiscoveryTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Custom annotation class discovery',
+      'description' => 'Tests that a custom annotation class is used.',
+      'group' => 'Plugin API',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    $this->expectedDefinitions = array(
+      'example_1' => array(
+        'id' => 'example_1',
+        'custom' => 'John',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\custom_annotation\Example1',
+      ),
+      'example_2' => array(
+        'id' => 'example_2',
+        'custom' => 'Paul',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\custom_annotation\Example2',
+      ),
+    );
+    $root_namespaces = array('Drupal\plugin_test' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib');
+    $annotation_namespaces = array(
+      'Drupal\plugin_test\Plugin\Annotation' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib',
+    );
+
+    $this->discovery = new AnnotatedClassDiscovery('plugin_test', 'custom_annotation', $root_namespaces, $annotation_namespaces, 'Drupal\plugin_test\Plugin\Annotation\PluginExample');
+    $this->emptyDiscovery = new AnnotatedClassDiscovery('non_existing_module', 'non_existing_plugin_type', $root_namespaces, $annotation_namespaces, 'Drupal\plugin_test\Plugin\Annotation\PluginExample');
+  }
+
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Annotation/PluginExample.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Annotation/PluginExample.php
new file mode 100644
index 0000000..f830152
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Annotation/PluginExample.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\Annotation\PluginExample.
+ */
+
+namespace Drupal\plugin_test\Plugin\Annotation;
+
+use Drupal\Component\Annotation\AnnotationInterface;
+
+/**
+ * Defines a custom Plugin annotation.
+ *
+ * @Annotation
+ */
+class PluginExample implements AnnotationInterface {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * Another plugin metadata.
+   *
+   * @var string
+   */
+  public $custom;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get() {
+    return array(
+      'id' => $this->id,
+      'custom' => $this->custom,
+    );
+  }
+
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example1.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example1.php
new file mode 100644
index 0000000..269f3ed
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example1.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\custom_annotation\Example1.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\custom_annotation;
+
+use Drupal\plugin_test\Plugin\Annotation\PluginExample;
+
+/**
+ * Provides a test plugin with a custom annotation.
+ *
+ * @PluginExample(
+ *   id = "example_1",
+ *   custom = "John"
+ * )
+ */
+class Example1 {}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example2.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example2.php
new file mode 100644
index 0000000..1d668f7
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/custom_annotation/Example2.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\custom_annotation\Example2.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\custom_annotation;
+
+use Drupal\plugin_test\Plugin\Annotation\PluginExample;
+
+/**
+ * Provides a test plugin with a custom annotation.
+ *
+ * @PluginExample(
+ *   id = "example_2",
+ *   custom = "Paul"
+ * )
+ */
+class Example2 {}
diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
index ee6c02c..50c6cdd 100644
--- a/core/modules/toolbar/js/toolbar.js
+++ b/core/modules/toolbar/js/toolbar.js
@@ -58,7 +58,7 @@
       if (subtrees) {
         for (var id in subtrees) {
           if (subtrees.hasOwnProperty(id)) {
-            $('#toolbar-link-' + id).after(subtrees.id);
+            $('#toolbar-link-' + id).after(subtrees[id]);
           }
         }
       }
diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
index e4bd339..2762d4f 100644
--- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -322,6 +322,7 @@ public function getStandardButtons(&$form, &$form_state, $form_id, $name = NULL)
       '#value' => empty($form_state['ok_button']) ? t('Cancel') : t('Ok'),
       '#submit' => array($cancel_submit),
       '#validate' => array(),
+      '#attributes' => array('formnovalidate' => ''),
     );
 
     // Compatibility, to be removed later: // TODO: When is "later"?
