diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index 225cb73..364cad2 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -1,4 +1,4 @@
-(function ($) {
+(function ($, Drupal) {
 
 "use strict";
 
@@ -6,115 +6,265 @@
  * Attaches sticky table headers.
  */
 Drupal.behaviors.tableHeader = {
-  attach: function (context, settings) {
+  attach: function (context) {
     if (!$.support.fixedPosition) {
       return;
     }
-
-    $(context).find('table.sticky-enabled').once('tableheader', function () {
-      $(this).data("drupal-tableheader", new Drupal.tableHeader(this));
-    });
+    $(window).one('scroll.TableHeaderInit', {context: context}, tableHeaderInitHandler);
   }
 };
 
+function scrollValue(position) {
+  return document.documentElement[position] || document.body[position];
+}
+
+// Select and initilize sticky table headers.
+function tableHeaderInitHandler(e) {
+  var $tables = $(e.data.context).find('table.sticky-enabled').once('tableheader');
+  for (var i = 0, il = $tables.length; i < il; i++) {
+    TableHeader.tables.push(new TableHeader($tables[i]));
+  }
+}
+
+// Helper method to loop through tables and execute a method.
+function forTables(method, arg) {
+  var tables = TableHeader.tables;
+  for (var i = 0, il = tables.length; i < il; i++) {
+    tables[i][method](arg);
+  }
+}
+
+function tableHeaderResizeHandler(e) {
+  forTables('recalculateSticky');
+}
+
+function tableHeaderOnScrollHandler(e) {
+  forTables('onScroll');
+}
+
+function tableHeaderOffsetChangeHandler(e) {
+  // Compute the new offset value.
+  TableHeader.computeOffsetTop();
+  forTables('stickyPosition', TableHeader.offsetTop);
+}
+
+// Bind event that need to change all tables.
+$(window).on({
+  /**
+   * When resizing table width and offset top can change, recalculate everything.
+   */
+  'resize.TableHeader': tableHeaderResizeHandler,
+
+  /**
+   * Bind only one event to take care of calling all scroll callbacks.
+   */
+  'scroll.TableHeader': tableHeaderOnScrollHandler
+});
+// Bind to custom Drupal events.
+$(document).on({
+  /**
+   * Recalculate columns width when window is resized and when show/hide
+   * weight is triggered.
+   */
+  'columnschange.TableHeader': tableHeaderResizeHandler,
+
+  /**
+   * Offset value vas changed by a third party script.
+   */
+  'offsettopchange.TableHeader': tableHeaderOffsetChangeHandler
+});
+
 /**
  * Constructor for the tableHeader object. Provides sticky table headers.
  *
+ * TableHeader will make the current table header stick to the top of the page
+ * if the table is very long.
+ *
+ * Fire a custom "topoffsetchange" event to make TableHeader compute the
+ * new offset value from the "data-offset-top" attributes of relevant elements.
+ *
  * @param table
  *   DOM object for the table to add a sticky header to.
+ *
+ * @constructor
  */
-Drupal.tableHeader = function (table) {
-  var self = this;
+function TableHeader(table) {
   var $table = $(table);
 
-  this.originalTable = $table;
-  this.originalHeader = $table.children('thead');
-  this.originalHeaderCells = this.originalHeader.find('> tr > th');
+  this.$originalTable = $table;
+  this.$originalHeader = $table.children('thead');
+  this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
   this.displayWeight = null;
 
+  this.$originalTable.addClass('sticky-table');
+  this.tableHeight = $table[0].clientHeight;
+  this.tableOffset = this.$originalTable.offset();
+
   // React to columns change to avoid making checks in the scroll callback.
-  this.originalTable.bind('columnschange', function (e, display) {
-    // This will force header size to be calculated on scroll.
-    self.widthCalculated = (self.displayWeight !== null && self.displayWeight === display);
-    self.displayWeight = display;
+  this.$originalTable.bind('columnschange', {tableHeader: this}, function (e, display) {
+    var tableHeader = e.data.tableHeader;
+    if (tableHeader.displayWeight === null || tableHeader.displayWeight !== display) {
+      tableHeader.recalculateSticky();
+    }
+    tableHeader.displayWeight = display;
   });
 
-  // Clone the table header so it inherits original jQuery properties. Hide
-  // the table to avoid a flash of the header clone upon page load.
-  this.stickyTable = $('<table class="sticky-header"/>')
-    .insertBefore(this.originalTable)
-    .css({ position: 'fixed', top: '0px' });
-  this.stickyHeader = this.originalHeader.clone(true)
-    .hide()
-    .appendTo(this.stickyTable);
-  this.stickyHeaderCells = this.stickyHeader.find('> tr > th');
-
-  this.originalTable.addClass('sticky-table');
-  $(window)
-    .bind('scroll.drupal-tableheader', $.proxy(this, 'eventhandlerRecalculateStickyHeader'))
-    .bind('resize.drupal-tableheader', { calculateWidth: true }, $.proxy(this, 'eventhandlerRecalculateStickyHeader'))
-    // Make sure the anchor being scrolled into view is not hidden beneath the
-    // sticky table header. Adjust the scrollTop if it does.
-    .bind('drupalDisplaceAnchor.drupal-tableheader', function () {
-      window.scrollBy(0, -self.stickyTable.outerHeight());
-    })
-    // Make sure the element being focused is not hidden beneath the sticky
-    // table header. Adjust the scrollTop if it does.
-    .bind('drupalDisplaceFocus.drupal-tableheader', function (event) {
-      if (self.stickyVisible && event.clientY < (self.stickyOffsetTop + self.stickyTable.outerHeight()) && event.$target.closest('sticky-header').length === 0) {
-        window.scrollBy(0, -self.stickyTable.outerHeight());
-      }
-    })
-    .triggerHandler('resize.drupal-tableheader');
-
-  // We hid the header to avoid it showing up erroneously on page load;
-  // we need to unhide it now so that it will show up when expected.
-  this.stickyHeader.show();
-};
+  // Create and display sticky header.
+  this.createSticky();
+}
 
 /**
- * Event handler: recalculates position of the sticky table header.
- *
- * @param event
- *   Event being triggered.
+ * Store the state of TableHeader.
  */
-Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (event) {
-  var self = this;
-  var calculateWidth = event.data && event.data.calculateWidth;
-
-  // Reset top position of sticky table headers to the current top offset.
-  this.stickyOffsetTop = Drupal.settings.tableHeaderOffset ? eval(Drupal.settings.tableHeaderOffset + '()') : 0;
-  this.stickyTable.css('top', this.stickyOffsetTop + 'px');
-
-  // Save positioning data.
-  var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
-  if (calculateWidth || this.viewHeight !== viewHeight) {
-    this.viewHeight = viewHeight;
-    this.vPosition = this.originalTable.offset().top - 4 - this.stickyOffsetTop;
-    this.hPosition = this.originalTable.offset().left;
-    this.vLength = this.originalTable[0].clientHeight - 100;
-    calculateWidth = true;
+$.extend(TableHeader, {
+  /**
+   * This will store the state of all processed tables.
+   *
+   * @type {Array}
+   */
+  tables: [],
+
+  /**
+   * Cache of computed offset value.
+   *
+   * @type {Number}
+   */
+  offsetTop: 0,
+
+  /**
+   * Sum all [data-offset-top] values and cache it.
+   */
+  computeOffsetTop: function () {
+    var $offsets = $('[data-offset-top]');
+    var value, sum = 0;
+    for (var i = 0, il = $offsets.length; i < il; i++) {
+      value = parseInt($offsets[i].getAttribute('data-offset-top'), 10);
+      sum += !isNaN(value) ? value : 0;
+    }
+    this.offsetTop = sum;
+    return sum;
   }
+});
+
+/**
+ * Extend TableHeader prototype.
+ */
+$.extend(TableHeader.prototype, {
+  /**
+   * Minimum height in pixels for the table to have a sticky header.
+   */
+  minHeight: 100,
+
+  /**
+   * Absolute position of the table on the page.
+   */
+  tableOffset: null,
+
+  /**
+   * Absolute position of the table on the page.
+   */
+  tableHeight: null,
+
+  /**
+   * Boolean storing the sticky header visibility state.
+   */
+  stickyVisible: false,
+
+  /**
+   * Create the duplicate header.
+   */
+  createSticky: function () {
+    // Clone the table header so it inherits original jQuery properties.
+    var $stickyHeader = this.$originalHeader.clone(true);
+    // Hide the table to avoid a flash of the header clone upon page load.
+    this.$stickyTable = $('<table class="sticky-header"/>')
+      .css({
+        visibility: 'hidden',
+        position: 'fixed',
+        top: '0px'
+      })
+      .append($stickyHeader)
+      .insertBefore(this.$originalTable);
+
+    this.$stickyHeaderCells = $stickyHeader.find('> tr > th');
+
+    // Initialize all computations.
+    this.recalculateSticky();
+  },
 
-  // Track horizontal positioning relative to the viewport and set visibility.
-  var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
-  var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - this.vPosition;
-  this.stickyVisible = vOffset > 0 && vOffset < this.vLength;
-  this.stickyTable.css({ left: (-hScroll + this.hPosition) + 'px', visibility: this.stickyVisible ? 'visible' : 'hidden' });
+  /**
+   * Set absolute position of sticky.
+   *
+   * @param offsetTop
+   * @param offsetLeft
+   */
+  stickyPosition: function (offsetTop, offsetLeft) {
+    var css = {};
+    if (!isNaN(offsetTop)) {
+      css.top = offsetTop + 'px';
+    }
+    if (!isNaN(offsetLeft)) {
+      css.left = (this.tableOffset.left - offsetLeft) + 'px';
+    }
+    return this.$stickyTable.css(css);
+  },
+
+  /**
+   * Returns true if sticky is currently visible.
+   */
+  checkStickyVisible: function () {
+    var scrollTop = scrollValue('scrollTop');
+    var tableTop = this.tableOffset.top - TableHeader.offsetTop;
+    var tableBottom = tableTop + this.tableHeight;
+    var visible = false;
+
+    if (tableTop < scrollTop && scrollTop < (tableBottom - this.minHeight)) {
+      visible = true;
+    }
+
+    this.stickyVisible = visible;
+    return visible;
+  },
 
-  // Only perform expensive calculations if the sticky header is actually
-  // visible or when forced.
-  if (this.stickyVisible && (calculateWidth || !this.widthCalculated)) {
-    this.widthCalculated = true;
+  /**
+   * Check if sticky header should be displayed.
+   *
+   * This function is throttled to once every 250ms to avoid unnecessary calls.
+   *
+   * @param event
+   */
+  onScroll: function (e) {
+    this.checkStickyVisible();
+    // Track horizontal positioning relative to the viewport.
+    this.stickyPosition(null, scrollValue('scrollLeft'));
+    this.$stickyTable.css('visibility', this.stickyVisible ? 'visible' : 'hidden');
+  },
+
+  /**
+   * Event handler: recalculates position of the sticky table header.
+   *
+   * @param event
+   *   Event being triggered.
+   */
+  recalculateSticky: function (event) {
+    // Update table size.
+    this.tableHeight = this.$originalTable[0].clientHeight;
+
+    // Update offset top.
+    TableHeader.computeOffsetTop();
+    this.tableOffset = this.$originalTable.offset();
+    this.stickyPosition(TableHeader.offsetTop);
+
+    // Update columns width.
     var $that = null;
     var $stickyCell = null;
     var display = null;
     // Resize header and its cell widths.
     // Only apply width to visible table cells. This prevents the header from
     // displaying incorrectly when the sticky header is no longer visible.
-    for (var i = 0, il = this.originalHeaderCells.length; i < il; i += 1) {
-      $that = $(this.originalHeaderCells[i]);
-      $stickyCell = this.stickyHeaderCells.eq($that.index());
+    for (var i = 0, il = this.$originalHeaderCells.length; i < il; i++) {
+      $that = $(this.$originalHeaderCells[i]);
+      $stickyCell = this.$stickyHeaderCells.eq($that.index());
       display = $that.css('display');
       if (display !== 'none') {
         $stickyCell.css({'width': $that.css('width'), 'display': display});
@@ -123,8 +273,11 @@ Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (eve
         $stickyCell.css('display', 'none');
       }
     }
-    this.stickyTable.css('width', this.originalTable.css('width'));
+    this.$stickyTable.css('width', this.$originalTable.outerWidth());
   }
-};
+});
+
+// Expose constructor in the public space.
+Drupal.TableHeader = TableHeader;
 
-})(jQuery);
+}(jQuery, Drupal));
diff --git a/core/modules/overlay/overlay-child.js b/core/modules/overlay/overlay-child.js
index 6a2da9e..e1f8ff1 100644
--- a/core/modules/overlay/overlay-child.js
+++ b/core/modules/overlay/overlay-child.js
@@ -174,23 +174,11 @@ Drupal.overlayChild.behaviors.shortcutAddLink = function (context, settings) {
   });
 };
 
-/**
- * Use displacement from parent window.
- */
-Drupal.overlayChild.behaviors.alterTableHeaderOffset = function (context, settings) {
-  if (Drupal.settings.tableHeaderOffset) {
-    Drupal.overlayChild.prevTableHeaderOffset = Drupal.settings.tableHeaderOffset;
-  }
-  Drupal.settings.tableHeaderOffset = 'Drupal.overlayChild.tableHeaderOffset';
-};
-
-/**
- * Callback for Drupal.settings.tableHeaderOffset.
- */
-Drupal.overlayChild.tableHeaderOffset = function () {
-  var topOffset = Drupal.overlayChild.prevTableHeaderOffset ? eval(Drupal.overlayChild.prevTableHeaderOffset + '()') : 0;
-
-  return topOffset + parseInt($(document.body).css('marginTop'));
-};
+// Workaround because of the way jQuery events works.
+// jQuery from the parent frame needs to be used to catch this event.
+parent.jQuery(document).bind('offsettopchange', function () {
+  // Fires an event that the child iframe can listen to.
+  $(document).trigger('offsettopchange');
+});
 
 })(jQuery);
diff --git a/core/modules/overlay/overlay-parent.js b/core/modules/overlay/overlay-parent.js
index 9c0b527..64294d9 100644
--- a/core/modules/overlay/overlay-parent.js
+++ b/core/modules/overlay/overlay-parent.js
@@ -433,6 +433,12 @@ Drupal.overlay.eventhandlerAlterDisplacedElements = function (event) {
   $(this.iframeWindow.document.body).css({
     marginTop: Drupal.overlay.getDisplacement('top'),
     marginBottom: Drupal.overlay.getDisplacement('bottom')
+  }).attr('data-offset-top', Drupal.overlay.getDisplacement('top'));
+
+  $(document).bind('offsettopchange', function () {
+    var iframeDocument = Drupal.overlay.iframeWindow.document;
+    $(iframeDocument.body).attr('data-offset-top', Drupal.overlay.getDisplacement('top'));
+    $(iframeDocument).trigger('offsettopchange');
   });
 
   var documentHeight = this.iframeWindow.document.body.clientHeight;
diff --git a/core/modules/toolbar/toolbar.js b/core/modules/toolbar/toolbar.js
index ce775de..2353050 100644
--- a/core/modules/toolbar/toolbar.js
+++ b/core/modules/toolbar/toolbar.js
@@ -8,18 +8,23 @@ Drupal.toolbar = Drupal.toolbar || {};
  * Attach toggling behavior and notify the overlay of the toolbar.
  */
 Drupal.behaviors.toolbar = {
-  attach: function(context) {
-    var $context = $(context);
-    // Set the initial state of the toolbar.
-    $context.find('#toolbar').once('toolbar', Drupal.toolbar.init);
+  attach: function(context, settings) {
+    var $toolbar = $('#toolbar').once('toolbar');
+    if ($toolbar.length) {
 
-    // Toggling toolbar drawer.
-    $context.find('#toolbar a.toggle').once('toolbar-toggle').click(function(e) {
-      Drupal.toolbar.toggle();
-      // Allow resize event handlers to recalculate sizes/positions.
-      $(window).triggerHandler('resize');
-      return false;
-    });
+      // Set the initial state of the toolbar.
+      Drupal.toolbar.init();
+
+      $(window).on('resize.toolbar', Drupal.toolbar.height);
+
+      // Toggling toolbar drawer.
+      $toolbar.find('a.toggle').once('toolbar-toggle').click(function(e) {
+        e.preventDefault();
+        Drupal.toolbar.toggle();
+        // Allow resize event handlers to recalculate sizes/positions.
+        $(window).triggerHandler('resize');
+      });
+    }
   }
 };
 
@@ -59,6 +64,8 @@ Drupal.toolbar.collapse = function() {
       expires: 36500
     }
   );
+  Drupal.toolbar.height();
+  $(document).trigger('offsettopchange');
 };
 
 /**
@@ -81,6 +88,8 @@ Drupal.toolbar.expand = function() {
       expires: 36500
     }
   );
+  Drupal.toolbar.height();
+  $(document).trigger('offsettopchange');
 };
 
 /**
@@ -96,8 +105,10 @@ Drupal.toolbar.toggle = function() {
 };
 
 Drupal.toolbar.height = function() {
+  // @TODO this needs to be cached outside this function.
   var $toolbar = $('#toolbar');
   var height = $toolbar.outerHeight();
+  $toolbar.attr('data-offset-top', height);
   return height;
 };
 
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 70f12bf..5831d46 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -194,10 +194,6 @@ function toolbar_view() {
     '#attached'=> array(
       'js' => array(
         $module_path . '/toolbar.js',
-        array(
-          'data' => array('tableHeaderOffset' => 'Drupal.toolbar.height'),
-          'type' => 'setting'
-        ),
       ),
       'css' => array(
         $module_path . '/toolbar.css',
