diff --git a/core/includes/common.inc b/core/includes/common.inc
index 654d849..aec968e 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1928,19 +1928,6 @@ function l($text, $path, array $options = array()) {
     'html' => FALSE,
   );
 
-  // Append active class.
-  // The link is only active, if its path corresponds to the current path, the
-  // language of the linked path is equal to the current language, and if the
-  // query parameters of the link equal those of the current request, since the
-  // same request with different query parameters may yield a different page
-  // (e.g., pagers).
-  $is_active = ($path == current_path() || ($path == '<front>' && drupal_is_front_page()));
-  $is_active = $is_active && (empty($options['language']) || $options['language']->langcode == language(LANGUAGE_TYPE_URL)->langcode);
-  $is_active = $is_active && (drupal_container()->get('request')->query->all() == $options['query']);
-  if ($is_active) {
-    $options['attributes']['class'][] = 'active';
-  }
-
   // Remove all HTML and PHP tags from a tooltip. For best performance, we act only
   // if a quick strpos() pre-check gave a suspicion (because strip_tags() is expensive).
   if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) {
@@ -3433,10 +3420,13 @@ function drupal_add_js($data = NULL, $options = NULL) {
           $pathPrefix = '';
           url('', array('script' => &$scriptPath, 'prefix' => &$pathPrefix));
           $javascript['settings']['data'][] = array(
-            'basePath' => base_path(),
-            'scriptPath' => $scriptPath,
-            'pathPrefix' => $pathPrefix,
-            'currentPath' => current_path(),
+            'path' => array(
+              'basePath' => base_path(),
+              'scriptPath' => $scriptPath,
+              'pathPrefix' => $pathPrefix,
+              'currentPath' => current_path(),
+              'isFront' => drupal_is_front_page(),
+            ),
           );
         }
         // All JavaScript settings are placed in the header of the page with
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 627e264..28a074f 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -12,6 +12,27 @@ jQuery.noConflict();
 // Populate Drupal.settings with the drupalSettings variable.
 Drupal.settings = drupalSettings;
 
+// Append active class.
+// The link is only active, if its path corresponds to the current path, the
+// language of the linked path is equal to the current language, and if the
+// query parameters of the link equal those of the current request, since the
+// same request with different query parameters may yield a different page
+// (e.g., pagers).
+Drupal.behaviors.l = {
+  attach: function (context) {
+    var selectors = ['a[href="' + Drupal.url(drupalSettings.path.currentPath) + '"]'];
+    if (drupalSettings.path.isFront) {
+      selectors.push('a[href="' + Drupal.url('') + '"]');
+    }
+    $(context).find(selectors.join(',')).addClass('active');
+  },
+  detach: function (context, settings, trigger) {
+    if (trigger === 'unload') {
+      $(context).find('a.active').removeClass('active');
+    }
+  }
+};
+
 /**
  * Custom error type thrown after attach/detach if one or more behaviors failed.
  *
@@ -262,7 +283,7 @@ Drupal.t = function (str, args, options) {
  * Returns the URL to a Drupal page.
  */
 Drupal.url = function (path) {
-  return drupalSettings.basePath + drupalSettings.scriptPath + path;
+  return drupalSettings.path.basePath + drupalSettings.path.scriptPath + path;
 };
 
 /**
diff --git a/core/modules/overlay/overlay-parent.js b/core/modules/overlay/overlay-parent.js
index 3356580..5f78104 100644
--- a/core/modules/overlay/overlay-parent.js
+++ b/core/modules/overlay/overlay-parent.js
@@ -828,7 +828,7 @@ Drupal.overlay.getPath = function (link) {
   if (path.charAt(0) !== '/') {
     path = '/' + path;
   }
-  path = path.replace(new RegExp(Drupal.settings.basePath + Drupal.settings.scriptPath), '');
+  path = path.replace(new RegExp(drupalSettings.path.basePath + drupalSettings.path.scriptPath), '');
 
   return path;
 };
diff --git a/core/modules/toolbar/js/toolbar.menu.js b/core/modules/toolbar/js/toolbar.menu.js
index f05bcb0..8deb14c 100644
--- a/core/modules/toolbar/js/toolbar.menu.js
+++ b/core/modules/toolbar/js/toolbar.menu.js
@@ -12,7 +12,7 @@
 /**
  * Store the open menu tray.
  */
-var activeItem = drupalSettings.basePath + drupalSettings.currentPath;
+var activeItem = drupalSettings.path.basePath + drupalSettings.path.currentPath;
 
   $.fn.toolbarMenu = function () {
 
diff --git a/core/modules/views/js/base.js b/core/modules/views/js/base.js
index 5cb7e5e..a375697 100644
--- a/core/modules/views/js/base.js
+++ b/core/modules/views/js/base.js
@@ -63,7 +63,7 @@
    */
   Drupal.Views.getPath = function (href) {
     href = Drupal.Views.pathPortion(href);
-    href = href.substring(Drupal.settings.basePath.length, href.length);
+    href = href.substring(drupalSettings.path.basePath.length, href.length);
     // 3 is the length of the '?q=' added to the url without clean urls.
     if (href.substring(0, 3) === '?q=') {
       href = href.substring(3, href.length);
