File: //old_home_backup/brucelee.org.uk/public_html/ext_iframe/uds/solutions/videobar/gsvideobar.js
/**
* Copyright (c) 2008 Google Inc.
*
* You are free to copy and use this sample.
* License can be found here: http://code.google.com/apis/ajaxsearch/faq/#license
*/
function GSvideoBar(barRoot, opt_playerRoot, options) {
this.processArguments(barRoot, opt_playerRoot, options);
this.setGlobals();
this.buildSuperStructure();
this.buildSearchControl();
// if we have an auto execute list, then start it up
if (this.autoExecuteMode) {
this.cycleTimeClosure = this.methodClosure(this, GSvideoBar.prototype.cycleTimeout, [null]);
// if there is only a single item in the execute list, then
// disable autoExecuteMode...
if ( this.executeList.length == 1) {
this.switchToListItem(0);
} else {
this.cycleTimeout();
}
}
}
// cycle time for selecting a video set
GSvideoBar.CYCLE_TIME_EXTRA_SHORT = 3000;
GSvideoBar.CYCLE_TIME_SHORT = 10000;
GSvideoBar.CYCLE_TIME_MEDIUM = 15000;
GSvideoBar.CYCLE_TIME_LONG = 30000;
// cycle mode
GSvideoBar.CYCLE_MODE_RANDOM = 1;
GSvideoBar.CYCLE_MODE_LINEAR = 2;
GSvideoBar.MAX_CACHE_LIFETIME = 50;
GSvideoBar.MIN_CACHE_LIFETIME = 2;
GSvideoBar.DEFAULT_CACHE_LIFETIME = 2;
GSvideoBar.MAX_ERROR_COUNT = 4;
GSvideoBar.DEFAULT_QUERY = "VW GTI";
GSvideoBar.THUMBNAILS_SMALL = 1;
GSvideoBar.THUMBNAILS_MEDIUM = 2;
// floating player option
GSvideoBar.PLAYER_ROOT_FLOATING = "floating";
GSvideoBar.prototype.processArguments = function(barRoot, opt_playerRoot,
opt_options) {
this.floatingPlayerBox = null;
this.barRoot = barRoot;
this.playerRoot = opt_playerRoot;
this.statusRoot = null;
this.externalMaster = null;
this.verticalMode = true;
this.thumbSize = GSvideoBar.THUMBNAILS_MEDIUM;
this.autoExecuteMode = false;
this.executeList = new Array();
this.cycleTime = GSvideoBar.CYCLE_TIME_MEDIUM;
this.cycleMode = GSvideoBar.CYCLE_MODE_RANDOM;
this.cycleNext = 0;
this.cycleTimer = null;
this.cacheLifetime = GSvideoBar.DEFAULT_CACHE_LIFETIME;
// set defaults that are changable via options
this.resultSetSize = GSearch.SMALL_RESULTSET;
this.ST_ALL_DONE = GSearch.strings["im-done"];
if (opt_options) {
// option.largetResultSet
if (opt_options.largeResultSet && opt_options.largeResultSet == true ) {
this.resultSetSize = GSearch.LARGE_RESULTSET;
} else {
this.resultSetSize = GSearch.SMALL_RESULTSET;
}
if ( opt_options.master ) {
this.externalMaster = opt_options.master;
}
if (opt_options.horizontal && opt_options.horizontal == true ) {
this.verticalMode = false;
} else {
this.verticalMode = true;
}
if (opt_options.thumbnailSize) {
if (opt_options.thumbnailSize == GSvideoBar.THUMBNAILS_MEDIUM ) {
this.thumbSize = GSvideoBar.THUMBNAILS_MEDIUM;
} else if ( opt_options.thumbnailSize == GSvideoBar.THUMBNAILS_SMALL ) {
this.thumbSize = GSvideoBar.THUMBNAILS_SMALL;
} else {
this.thumbSize = GSvideoBar.THUMBNAILS_MEDIUM;
}
}
if (opt_options.string_allDone) {
this.ST_ALL_DONE = opt_options.string_allDone;
}
// the auto execute list contains
// a cycleTime value, a cycleMode value, and an array
// of searchExpressions
if (opt_options.autoExecuteList) {
// if specified and valid, then use it, otherwise
// use default set above
if (opt_options.autoExecuteList.cycleTime) {
var cycleTime = opt_options.autoExecuteList.cycleTime;
if (cycleTime == GSvideoBar.CYCLE_TIME_EXTRA_SHORT ||
cycleTime == GSvideoBar.CYCLE_TIME_SHORT ||
cycleTime == GSvideoBar.CYCLE_TIME_MEDIUM ||
cycleTime == GSvideoBar.CYCLE_TIME_LONG ) {
this.cycleTime = cycleTime;
}
}
if (opt_options.autoExecuteList.cycleMode) {
var cycleMode = opt_options.autoExecuteList.cycleMode;
if (cycleMode == GSvideoBar.CYCLE_MODE_RANDOM ||
cycleMode == GSvideoBar.CYCLE_MODE_LINEAR) {
this.cycleMode = cycleMode;
}
}
// now grab the list...
if (opt_options.autoExecuteList.executeList &&
opt_options.autoExecuteList.executeList.length > 0 ) {
// grab from the list
for (var i=0; i < opt_options.autoExecuteList.executeList.length; i++) {
this.executeList.push(
this.newListItem(opt_options.autoExecuteList.executeList[i]));
}
this.autoExecuteMode = true;
this.currentIndex = 0;
if (opt_options.autoExecuteList.statusRoot) {
this.statusRoot = opt_options.autoExecuteList.statusRoot;
}
}
}
}
}
GSvideoBar.prototype.resetAutoExecuteListItems = function(newList) {
if (this.autoExecuteMode && newList.length > 0) {
// stop the timer...
if (this.cycleTimer) {
clearTimeout(this.cycleTimer);
this.cycleTimer = null;
}
// clear the status area
if (this.statusRoot) {
this.removeChildren(this.statusRoot);
}
// nuke the old list
this.executeList = new Array();
// build the new list
for (var i=0; i < newList.length; i++) {
this.executeList.push(this.newListItem(newList[i]));
}
this.currentIndex = 0;
if (this.statusRoot) {
this.populateStatusRoot();
}
if ( this.executeList.length == 1) {
this.switchToListItem(0);
} else {
this.cycleTimeout();
}
}
}
GSvideoBar.prototype.setGlobals = function() {
this.br_AgentContains_cache_ = {};
// subserstructure boxes
this.CL_PLAYERBOX = "playerBox_gsvb";
this.CL_PLAYING = "playerBox_gsvb playing_gsvb";
this.CL_IDLE = "playerBox_gsvb idle_gsvb";
this.CL_FLOATING_BOX = "floatingPlayerBox_gsvb";
this.CL_FLOATING_BRANDING = "floatingBranding_gsvb";
this.CL_FLOATING_BOX_PLAYING = "floatingPlayerBox_gsvb playing_gsvb";
this.CL_FLOATING_BOX_IDLE = "floatingPlayerBox_gsvb idle_gsvb";
this.CL_FLOATING_PLAYER = "floatingPlayer_gsvb";
this.CL_FLOATING_PLAYER_PLAYING = "floatingPlayer_gsvb playing_gsvb";
this.CL_FLOATING_PLAYER_IDLE = "floatingPlayer_gsvb idle_gsvb";
this.CL_PLAYERINNERBOX = "playerInnerBox_gsvb";
this.CL_VIDEOBARBOX = "videoBarBox_gsvb";
this.CL_VIDEOBARBOXFULL = "videoBarBox_gsvb full_gsvb";
this.CL_VIDEOBARBOXEMPTY = "videoBarBox_gsvb empty_gsvb";
// major app states
this.CL_ACTIVE = "active_gsvb";
// player
this.CL_PLAYER = "player_gsvb";
this.CL_ALLDONE = "alldone_gsvb";
this.CL_TITLE = "title_gsvb";
// results
this.CL_RESULTSBOX = "resultsBox_gsvb";
this.CL_BRANDINGBOX = "brandingBox_gsvb";
this.CL_RESULTTABLE_VERTICAL = "resultTable_gsvb vertical_gsvb";
this.CL_RESULTTABLE_HORIZONTAL = "resultTable_gsvb horizontal_gsvb";
this.CL_RESULTCELL = "resultCell_gsvb";
this.CL_RESULTDIV = "resultDiv_gsvb";
this.CL_RESULTDIV_SMALL = "resultDiv_gsvb smallResultDiv_gsvb";
// status
this.CL_STATUSBOX = "statusBox_gsvb";
this.CL_STATUSITEM = "statusItem_gsvb";
this.CL_STATUSITEM_SELECTED = "statusItem_gsvb statusItemSelected_gsvb";
this.smallResultBoxHeight = 39;
this.resultBoxHeight = 77;
}
GSvideoBar.prototype.buildSuperStructure = function() {
// build the player box if we are a master, if not
// link up to the master's player
if (this.externalMaster == null) {
if ( this.playerRoot == GSvideoBar.PLAYER_ROOT_FLOATING ) {
this.floatingPlayerBox = this.createDiv(null, this.CL_FLOATING_BOX_IDLE);
this.playerRoot = this.createDiv(null, this.CL_FLOATING_PLAYER_IDLE);
document.body.appendChild(this.floatingPlayerBox);
document.body.appendChild(this.playerRoot);
if (this.br_IsMac()) {
// disable opacity on mac
this.floatingPlayerBox.style.opacity = "1.00";
}
} else {
this.removeChildren(this.playerRoot);
}
this.playerBox = this.createDiv(null, this.CL_PLAYERBOX);
this.playerAllDone = this.createDiv(this.ST_ALL_DONE, this.CL_ALLDONE);
this.playerAllDone.onclick = this.methodClosure(this, this.stopVideo, []);
this.playerInnerBox = this.createDiv(null, this.CL_PLAYERINNERBOX);
this.playerBox.appendChild(this.playerAllDone);
this.playerBox.appendChild(this.playerInnerBox);
this.playerRoot.appendChild(this.playerBox);
this.cssSetClass(this.playerBox, this.CL_IDLE);
}
this.player = null;
// create the videoBar box
this.removeChildren(this.barRoot);
this.barBox = this.createDiv(null, this.CL_VIDEOBARBOX);
this.barRoot.appendChild(this.barBox);
// add results box and branding box
this.resultsBox = this.createDiv(null, this.CL_RESULTSBOX);
this.barBox.appendChild(this.resultsBox);
this.cssSetClass(this.barBox, this.CL_VIDEOBARBOXEMPTY);
// clear and optionally populate the status area
if (this.statusRoot) {
this.populateStatusRoot();
}
}
GSvideoBar.prototype.buildSearchControl = function() {
this.vs = new GvideoSearch();
this.vs.setResultSetSize(this.resultSetSize);
this.vs.setSearchCompleteCallback(this, GSvideoBar.prototype.searchComplete, [true]);
this.vsBypass = new GvideoSearch();
this.vsBypass.setResultSetSize(this.resultSetSize);
this.vsBypass.setSearchCompleteCallback(this, GSvideoBar.prototype.searchComplete, [false]);
}
GSvideoBar.prototype.execute = function(query) {
this.vsBypass.execute(query);
}
GSvideoBar.prototype.executeInternal = function(query) {
this.vs.execute(query);
}
GSvideoBar.prototype.clearAllResults = function() {
this.cssSetClass(this.barBox, this.CL_VIDEOBARBOXEMPTY);
}
GSvideoBar.prototype.searchComplete = function(fromListItem) {
var results = null;
if (fromListItem) {
var currentListItem = this.executeList[this.currentIndex];
if (this.vs.results && this.vs.results.length > 0) {
// populate cache
currentListItem.results = new Array();
currentListItem.cacheCount = 1;
currentListItem.errorCount = 0;
for (var i = 0; i < this.vs.results.length; i++) {
currentListItem.results.push(this.vs.results[i]);
}
results = currentListItem.results;
} else {
currentListItem.errorCount++;
// if the error is due to a bad search term, then
// nuke right away
if (this.vs.completionStatus == 200) {
currentListItem.errorCount = GSvideoBar.MAX_ERROR_COUNT + 1;
}
}
} else {
// normal .execute called, no caching...
if (this.vsBypass.results && this.vsBypass.results.length > 0) {
results = this.vsBypass.results;
}
}
this.processResults(results);
}
GSvideoBar.prototype.processResults = function(results) {
if ( results && results.length > 0) {
this.cssSetClass(this.barBox, this.CL_VIDEOBARBOXFULL);
this.removeChildren(this.resultsBox);
var cell;
var table;
var row = null;
if (this.verticalMode) {
table = this.createTable(this.CL_RESULTTABLE_VERTICAL);
} else {
table = this.createTable(this.CL_RESULTTABLE_HORIZONTAL);
}
table.setAttribute("align", "center");
for (var i = 0; i < results.length; i++) {
var res = results[i];
var imageScaler;
var resultBoxHeight;
var resultClass = null;
if (this.thumbSize == GSvideoBar.THUMBNAILS_MEDIUM ) {
// full size image
imageScaler = {width:100,height:75};
resultBoxHeight = this.resultBoxHeight;
resultClass = this.CL_RESULTDIV;
} else {
// small size image
imageScaler = {width:50,height:37};
resultBoxHeight = this.smallResultBoxHeight;
resultClass = this.CL_RESULTDIV_SMALL;
}
var scaled = GSearch.scaleImage(res.tbWidth, res.tbHeight, imageScaler);
var img = this.createImage(res.tbUrl, scaled.width, scaled.height, null);
if (this.externalMaster) {
img.onclick = this.methodClosure(this.externalMaster, this.externalMaster.playVideo, [res]);
} else {
img.onclick = this.methodClosure(this, this.playVideo, [res]);
}
// manually set the top padding
if ((resultBoxHeight - scaled.height) > 0) {
var padTop = Math.round((resultBoxHeight - scaled.height)/2);
img.setAttribute("vspace", padTop);
}
// compute duration
var seconds = res.duration;
var minutes = parseInt(seconds/60);
var durationString;
if (minutes > 0) {
durationString = minutes + "m";
var remainder = seconds%60;
if (remainder > 20) {
durationString += " " + remainder + "s";
}
} else {
durationString = seconds + "s";
}
var toolTip = res.titleNoFormatting + " ( " + durationString + " )";
var div = this.createDiv(null, resultClass);
div.title = toolTip;
div.appendChild(img);
// create a new row for each result when in vertical mode
// otherwise, jam everything into a single row.
if (this.verticalMode) {
row = this.createTableRow(table);
} else {
if (row == null) {
row = this.createTableRow(table);
}
}
cell = this.createTableCell(row, this.CL_RESULTCELL);
cell.setAttribute("align", "center");
cell.appendChild(div);
}
// now add in the branding...
row = this.createTableRow(table);
var brandingOrientation;
if (this.verticalMode) {
cell = this.createTableCell(row, this.CL_RESULTCELL);
brandingOrientation = GSearch.VERTICAL_BRANDING;
} else {
cell = this.createTableCell(row, this.CL_RESULTCELL);
if (this.br_IsIE()) {
cell.setAttribute("colSpan", results.length);
} else {
cell.setAttribute("colspan", results.length);
}
brandingOrientation = GSearch.HORIZONTAL_BRANDING;
}
GSearch.getBranding(cell, brandingOrientation, "http://www.youtube.com");
this.brandingCell = cell;
this.resultsBox.appendChild(table);
} else {
this.cssSetClass(this.barBox, this.CL_VIDEOBARBOXEMPTY);
}
}
GSvideoBar.prototype.playVideo = function(result) {
this.stopVideo();
if (this.autoExecuteMode && this.cycleTimer) {
clearTimeout(this.cycleTimer);
this.cycleTimer = null;
}
if (result.playUrl && result.playUrl != "") {
this.cssSetClass(this.playerBox, this.CL_PLAYING);
if (this.floatingPlayerBox) {
this.cssSetClass(this.floatingPlayerBox, this.CL_FLOATING_BOX_PLAYING);
this.cssSetClass(this.playerRoot, this.CL_FLOATING_PLAYER_PLAYING);
}
this.player = GvideoSearch.createPlayer(result, this.CL_PLAYER);
this.playerInnerBox.appendChild(this.player);
// the title
var title = this.createDivLink(result.url, result.title, null, this.CL_TITLE);
this.playerInnerBox.appendChild(title);
if (this.floatingPlayerBox) {
var playerBounds = GSvideoBar.nodeBounds(this.playerRoot);
var bounds = GSvideoBar.nodeBounds(this.barRoot);
var x;
var y;
if (this.verticalMode) {
x = bounds.x - playerBounds.width;
y = bounds.y + bounds.height / 2 - playerBounds.height / 2;
var brandingBounds = GSvideoBar.nodeBounds(this.brandingCell);
y = y - brandingBounds.height / 2;
if (x < 10) {
x = bounds.x + bounds.width;
}
} else {
x = bounds.x + bounds.width / 2 - playerBounds.width / 2;
y = bounds.y - playerBounds.height;
if (y < 10) {
y = bounds.y + bounds.height;
}
}
this.playerRoot.style.top = y + "px";
this.playerRoot.style.left = x + "px";
this.floatingPlayerBox.style.top = y - 10 + "px";
this.floatingPlayerBox.style.left = x - 10 + "px";
boxWidth = (playerBounds.width + 20) + "px";
this.floatingPlayerBox.style.width = boxWidth;
this.floatingPlayerBox.style.height = (playerBounds.height + 20) + "px";
}
}
}
GSvideoBar.prototype.stopVideo = function() {
this.cssSetClass(this.playerBox, this.CL_IDLE);
if (this.floatingPlayerBox) {
this.cssSetClass(this.floatingPlayerBox, this.CL_FLOATING_BOX_IDLE);
this.cssSetClass(this.playerRoot, this.CL_FLOATING_PLAYER_IDLE);
}
this.removeChildren(this.playerInnerBox);
if (this.player) {
delete(this.player);
this.player = null;
}
if (this.autoExecuteMode && this.executeList.length > 1) {
this.clearTimer();
this.cycleTimer = setTimeout(this.cycleTimeClosure, this.cycleTime);
}
}
GSvideoBar.prototype.clearTimer = function() {
if (this.cycleTimer) {
clearTimeout(this.cycleTimer);
this.cycleTimer = null;
}
}
GSvideoBar.prototype.cycleTimeout = function() {
// select a new video
// execute a search
// restart the timer
if ( this.player == null ) {
// if there is only a single item in the execute list,
// run it
if ( this.executeList.length == 1) {
this.switchToListItem(0);
} else {
var index = 0;
if (this.cycleMode == GSvideoBar.CYCLE_MODE_RANDOM) {
var max = this.executeList.length - 1;
index = Math.round(max * Math.random());
} else if (this.cycleMode == GSvideoBar.CYCLE_MODE_LINEAR){
index = this.cycleNext;
this.cycleNext++;
if (this.cycleNext >= this.executeList.length) {
this.cycleNext = 0;
}
}
this.switchToListItem(index);
this.clearTimer();
this.cycleTimer = setTimeout(this.cycleTimeClosure, this.cycleTime);
}
}
}
/**
* Autoexecute List Item Support
*/
GSvideoBar.prototype.newListItem = function(q) {
var listItem = new Object();
listItem.node = null;
listItem.query = q;
listItem.results = new Array();
listItem.errorCount = 0;
listItem.cacheCount = 0;
return listItem;
}
GSvideoBar.prototype.switchToListItem = function(i) {
// reset selcted class of previous item
// note, first time through this sets
// node 0
if (this.executeList[this.currentIndex].node) {
this.cssSetClass(this.executeList[this.currentIndex].node,
this.CL_STATUSITEM);
}
this.currentIndex = i;
if (this.executeList[this.currentIndex].node) {
this.cssSetClass(this.executeList[this.currentIndex].node,
this.CL_STATUSITEM_SELECTED);
}
var queryTerm = this.executeList[this.currentIndex].query;
var cacheResults = false;
var currentListItem = null;
currentListItem = this.executeList[this.currentIndex];
// if the error count of an item has reached max, reset query term
if (currentListItem.errorCount > GSvideoBar.MAX_ERROR_COUNT) {
currentListItem.errorCount = 0;
queryTerm = GSvideoBar.DEFAULT_QUERY;
currentListItem.query = queryTerm;
}
// if the listItem has no cached results, OR if
// we have used the cached results several times
// already, initiate a real search
if (currentListItem.cacheCount == 0 ||
currentListItem.cacheCount > this.cacheLifetime ) {
currentListItem.cacheCount = 0;
this.executeInternal(queryTerm);
} else {
currentListItem.cacheCount++;
this.processResults(currentListItem.results);
}
}
GSvideoBar.prototype.populateStatusRoot = function() {
this.removeChildren(this.statusRoot);
this.statusBox = this.createDiv(null, this.CL_STATUSBOX);
this.statusRoot.appendChild(this.statusBox);
if ( this.executeList.length > 0) {
for (var i=0; i < this.executeList.length; i++ ) {
var listItem = this.executeList[i];
var displayTerm = listItem.query;
// if we are looking at our special feed: terms, strip
// feed: from the display
var m = displayTerm.match(/feed:(top100|top100new)$/);
if (m && m.length == 2) {
displayTerm = m[1];
}
var div = this.createDiv(displayTerm, this.CL_STATUSITEM);
// add click handler...
div.onclick = this.methodClosure(this,
GSvideoBar.prototype.switchToListItem,
[i] );
listItem.node = div;
this.statusBox.appendChild(div);
this.statusBox.appendChild(document.createTextNode(" "));
}
}
}
/**
* Static Helper Method
*/
GSvideoBar.methodCallback = function(object, method) {
return function() {
return method.apply(object, arguments);
}
}
/**
* Class methods
*/
GSvideoBar.prototype.methodClosure = function(object, method, opt_argArray) {
return function() {
return method.apply(object, opt_argArray);
}
}
GSvideoBar.prototype.createDiv = function(opt_text, opt_className) {
var el = document.createElement("div");
if (opt_text) {
el.innerHTML = opt_text;
}
if (opt_className) { el.className = opt_className; }
return el;
}
GSvideoBar.prototype.removeChildren = function(parent) {
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
}
GSvideoBar.prototype.removeChild = function(parent, child) {
parent.removeChild(child);
}
GSvideoBar.prototype.cssSetClass = function(el, className) {
el.className = className;
}
GSvideoBar.prototype.createTable = function(opt_className) {
var el = document.createElement("table");
if (opt_className) { el.className = opt_className; }
return el;
}
GSvideoBar.prototype.createTableRow = function(table, opt_className) {
var tr = table.insertRow(-1);
if (opt_className) { tr.className = opt_className; }
return tr;
}
GSvideoBar.prototype.createTableCell = function(tr, opt_className) {
var td = tr.insertCell(-1);
if (opt_className) { td.className = opt_className; }
return td;
}
GSvideoBar.prototype.createDivLink = function(href, text, opt_target, opt_className) {
var div = this.createDiv(null, opt_className);
var el = document.createElement("a");
el.href = href;
el.appendChild(document.createTextNode(text));
if (opt_className) {
el.className = opt_className;
}
if (opt_target) {
el.target = opt_target;
}
div.appendChild(el);
return div;
}
GSvideoBar.prototype.createImage = function(src, opt_w, opt_h, opt_className) {
var el = document.createElement("img");
el.src = src;
if (opt_w) { el.width = opt_w; }
if (opt_h) { el.height = opt_h; }
if (opt_className) { el.className = opt_className; }
return el;
}
GSvideoBar.prototype.getNodeWidth = function(node) {
return node.offsetWidth;
}
GSvideoBar.prototype.br_AgentContains_ = function(str) {
if (str in this.br_AgentContains_cache_) {
return this.br_AgentContains_cache_[str];
}
return this.br_AgentContains_cache_[str] =
(navigator.userAgent.toLowerCase().indexOf(str) != -1);
}
GSvideoBar.prototype.br_IsIE = function() {
return this.br_AgentContains_('msie');
}
GSvideoBar.prototype.br_IsMac = function() {
return this.br_AgentContains_('macintosh') ||
this.br_AgentContains_('mac_powerpc');
}
GSvideoBar.prototype.br_IsKonqueror = function() {
return this.br_AgentContains_('konqueror');
}
GSvideoBar.prototype.br_IsOpera = function() {
return this.br_AgentContains_('opera');
}
GSvideoBar.prototype.br_IsSafari = function() {
return this.br_AgentContains_('safari') || this.br_IsKonqueror();
}
GSvideoBar.prototype.br_IsNav = function() {
return !this.br_IsIE() &&
!this.br_IsSafari() &&
this.br_AgentContains_('mozilla');
}
GSvideoBar.prototype.br_IsWin = function() {
return this.br_AgentContains_('win');
}
GSvideoBar.nodeBounds = function(obj) {
var result = {};
function fixRectForScrolling(r) {
// Need to take into account scrolling offset of ancestors (IE already does
// this)
for (var o = obj.offsetParent;
o && o.offsetParent;
o = o.offsetParent) {
if (o.scrollLeft) {
r.x -= o.scrollLeft;
}
if (o.scrollTop) {
r.y -= o.scrollTop;
}
}
}
// Mozilla
if (obj.ownerDocument && obj.ownerDocument.getBoxObjectFor) {
var box = obj.ownerDocument.getBoxObjectFor(obj);
result.x = box.x;
result.y = box.y;
result.width = box.width;
result.height = box.height;
fixRectForScrolling(result);
return result;
}
// IE
if (obj.getBoundingClientRect) {
var refWindow;
if (obj.ownerDocument && obj.ownerDocument.parentWindow) {
refWindow = obj.ownerDocument.parentWindow;
} else {
refWindow = window;
}
var rect = obj.getBoundingClientRect();
result.x = rect.left + GSvideoBar.GetIEScrollLeft(refWindow);
result.y = rect.top + GSvideoBar.GetIEScrollTop(refWindow);
result.width = rect.right - rect.left;
result.height = rect.bottom - rect.top;
return result;
}
// Fallback to recursively computing this
var left = 0;
var top = 0;
for (var o = obj; o.offsetParent; o = o.offsetParent) {
left += o.offsetLeft;
top += o.offsetTop;
}
result.x = left;
result.y = top;
result.width = obj.offsetWidth;
result.height = obj.offsetHeight;
fixRectForScrolling(result);
return result;
}
// Get the y position scroll offset.
GSvideoBar.GetIEScrollTop = function(win) {
if ("compatMode" in win.document && win.document.compatMode == "CSS1Compat") {
return win.document.documentElement.scrollTop;
} else {
return win.document.body.scrollTop;
}
}
// Get the x position scroll offset.
GSvideoBar.GetIEScrollLeft = function(win) {
if ("compatMode" in win.document && win.document.compatMode == "CSS1Compat") {
return win.document.documentElement.scrollLeft;
} else {
return win.document.body.scrollLeft;
}
}