features-extras.wave.dynamic-width.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shindig-extras Show documentation
Show all versions of shindig-extras Show documentation
Provides extra, deprecated or extended functionality. The items here have unstable APIs and could change at any time.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* 'License'); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
// TODO: Define a more convenient set of methods for iframe resizing in wave.
/**
* @fileoverview This library augments gadgets.window with functionality
* to change the width of a gadget dynamically. Derived from the
* dynamic-height feature source code.
* See:
* http://svn.apache.org/repos/asf/shindig/trunk/features/src/main/javascript/features/dynamic-height/dynamic-height.js
*/
/**
* @static
* @class This namespace is used by the Gadgets API for the features it offers
* in all containers, including Wave. Those are documented here:
* http://code.google.com/apis/gadgets/docs/reference/
* @name gadgets
*/
/**
* @static
* @class This namespace is defined by the Gadgets API, and documented here:
* http://code.google.com/apis/gadgets/docs/reference/#gadgets.window
* The Wave Gadgets API adds an additional method on top of the set documented
* there.
* @name gadgets.window
*/
gadgets.window = gadgets.window || {};
// we wrap these in an anonymous function to avoid storing private data
// as members of gadgets.window.
(function() {
var oldWidth;
/**
* Parse out the value (specified in px) for a CSS attribute of an element.
*
* @param {Element} elem the element with the attribute to look for.
* @param {string} attr the CSS attribute name of interest.
* @returns {number} the value of the px attr of the elem.
* @private
*/
function parseIntFromElemPxAttribute(elem, attr) {
var style = window.getComputedStyle(elem, "");
var value = style.getPropertyValue(attr);
value.match(/^([0-9]+)/);
return parseInt(RegExp.$1, 10);
}
/**
* For Webkit-based browsers, calculate the width of the gadget iframe by
* iterating through all elements in the gadget, starting with the body tag.
* It is not sufficient to only account body children elements, because
* CSS style position "float" may place a child element outside of the
* containing parent element. Not counting "float" elements may lead to
* undercounting.
*
* @returns {number} the width of the gadget.
* @private
*/
function getWidthForWebkit() {
var result = 0;
var queue = [ document.body ];
while (queue.length > 0) {
var elem = queue.shift();
var children = elem.childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (typeof child.offsetLeft !== 'undefined' &&
typeof child.scrollWidth !== 'undefined') {
// scrollHeight already accounts for border-bottom, padding-bottom.
var right = child.offsetLeft + child.scrollWidth +
parseIntFromElemPxAttribute(child, "margin-right");
result = Math.max(result, right);
}
queue.push(child);
}
}
// Add border, padding and margin of the containing body.
return result
+ parseIntFromElemPxAttribute(document.body, "border-right")
+ parseIntFromElemPxAttribute(document.body, "margin-right")
+ parseIntFromElemPxAttribute(document.body, "padding-right");
}
/**
* Adjusts the gadget width
* @param {number=} opt_width An optional preferred width in pixels. If not
* specified, will attempt to fit the gadget to its content.
* @member gadgets.window
*/
gadgets.window.adjustWidth = function(opt_width) {
var newWidth = parseInt(opt_width, 10);
var widthAutoCalculated = false;
if (isNaN(newWidth)) {
widthAutoCalculated = true;
// Resize the gadget to fit its content.
// Get the width of the viewport
var vw = gadgets.window.getViewportDimensions().width;
var body = document.body;
var docEl = document.documentElement;
if (document.compatMode === 'CSS1Compat' && docEl.scrollWidth) {
// In Strict mode:
// The inner content height is contained in either:
// document.documentElement.scrollWidth
// document.documentElement.offsetWidth
// Based on studying the values output by different browsers,
// use the value that's NOT equal to the viewport width found above.
newWidth = docEl.scrollWidth !== vw ?
docEl.scrollWidth : docEl.offsetWidth;
} else if (navigator.userAgent.indexOf('AppleWebKit') >= 0) {
// In Webkit:
// Property scrollWidth and offsetWidth will only increase in value.
// This will incorrectly calculate reduced width of a gadget
// (ie: made smaller).
newWidth = getWidthForWebkit();
} else if (body && docEl) {
// In Quirks mode:
// documentElement.clientWidth is equal to documentElement.offsetWidth
// except in IE. In most browsers, document.documentElement can be used
// to calculate the inner content width.
// However, in other browsers (e.g. IE), document.body must be used
// instead. How do we know which one to use?
// If document.documentElement.clientWidth does NOT equal
// document.documentElement.offsetWidth, then use document.body.
var sw = docEl.scrollWidth;
var ow = docEl.offsetWidth;
if (docEl.clientWidth !== ow) {
sw = body.scrollWidth;
ow = body.offsetWidth;
}
// Detect whether the inner content width is bigger or smaller
// than the bounding box (viewport). If bigger, take the larger
// value. If smaller, take the smaller value.
if (sw > vw) {
// Content is larger
newWidth = sw > ow ? sw : ow;
} else {
// Content is smaller
newWidth = sw < ow ? sw : ow;
}
}
}
// Only make the RPC call if width has changed
if (newWidth !== oldWidth &&
!isNaN(newWidth) &&
!(widthAutoCalculated && newWidth === 0)) {
oldWidth = newWidth;
gadgets.rpc.call(null, "setIframeWidth", null, newWidth);
}
};
}());
© 2015 - 2024 Weber Informatics LLC | Privacy Policy