summaryrefslogtreecommitdiff
path: root/misc/displace.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/displace.js')
-rw-r--r--misc/displace.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/misc/displace.js b/misc/displace.js
new file mode 100644
index 000000000..6345ff2c1
--- /dev/null
+++ b/misc/displace.js
@@ -0,0 +1,122 @@
+// $Id$
+(function ($) {
+
+/**
+ * Provides a generic method to position elements fixed to the viewport.
+ *
+ * Fixed positioning (CSS declaration position:fixed) is done relatively to the
+ * viewport. This makes it hard to position multiple fixed positioned element
+ * relative to each other (e.g. multiple toolbars should come after each other,
+ * not on top of each other).
+ *
+ * To position an element fixed at the top of the viewport add the class
+ * "displace-top" to that element, and to position it to the bottom of the view-
+ * port add the class "displace-bottom".
+ *
+ * When a browser doesn't support position:fixed (like IE6) the element gets
+ * positioned absolutely by default, but this can be overriden by using the
+ * "displace-unsupported" class.
+ */
+
+/**
+ * Attaches the displace behavior.
+ */
+Drupal.behaviors.displace = {
+ attach: function (context, settings) {
+ // Test for position:fixed support as IE6 does not.
+ // http://yura.thinkweb2.com/cft/#IS_POSITION_FIXED_SUPPORTED
+ if (this.supported === undefined) {
+ var el = $('<div style="position:fixed;top:10px"/>').appendTo(document.body);
+ this.supported = el[0].offsetTop === 10;
+ el.remove();
+
+ if (!this.supported) {
+ $(document.documentElement).addClass('displace-unsupported');
+ }
+ }
+
+ $(document.body).once('displace', function () {
+ $(window).bind('resize.drupal-displace', function () {
+ Drupal.displace.clearCache();
+
+ $(document.body).css({
+ paddingTop: Drupal.displace.getDisplacement('top'),
+ paddingBottom: Drupal.displace.getDisplacement('bottom')
+ });
+ });
+ });
+
+ Drupal.displace.clearCache(true);
+ $(window).triggerHandler('resize');
+ }
+};
+
+/**
+ * The displace object.
+ */
+Drupal.displace = Drupal.displace || {};
+
+Drupal.displace.elements = [];
+Drupal.displace.displacement = [];
+
+/**
+ * Get all displaced elements of given region.
+ *
+ * @param region
+ * Region name. Either "top" or "bottom".
+ *
+ * @return
+ * jQuery object containing all displaced elements of given region.
+ */
+Drupal.displace.getDisplacedElements = function (region) {
+ if (!this.elements[region]) {
+ this.elements[region] = $('.displace-' + region);
+ }
+ return this.elements[region];
+};
+
+/**
+ * Get the total displacement of given region.
+ *
+ * @param region
+ * Region name. Either "top" or "bottom".
+ *
+ * @return
+ * The total displacement of given region in pixels.
+ */
+Drupal.displace.getDisplacement = function (region) {
+ if (!this.displacement[region]) {
+ var offset = 0;
+ var height = 0;
+ this.getDisplacedElements(region).each(function () {
+ offset = offset + height;
+ height = $(this).css(region, offset).outerHeight();
+
+ // In IE, Shadow filter adds some extra height, so we need to remove it
+ // from the returned height.
+ if (this.filters && this.filters.length && this.filters.item('DXImageTransform.Microsoft.Shadow')) {
+ height -= this.filters.item('DXImageTransform.Microsoft.Shadow').strength;
+ }
+ });
+
+ // Use offset of latest displaced element as the total displacement.
+ this.displacement[region] = offset + height;
+ }
+
+ return this.displacement[region];
+};
+
+/**
+ * Clear cache.
+ *
+ * @param selectorCache
+ * Boolean whether to also clear the selector cache.
+ */
+Drupal.displace.clearCache = function (selectorCache) {
+ if (selectorCache) {
+ this.elements = [];
+ }
+ this.displacement = [];
+};
+
+})(jQuery);