/*****************************************************************************
scalable Inman Flash Replacement (sIFR) version 3, revision 436.
Copyright 2006 – 2008 Mark Wubben,
Older versions:
* IFR by Shaun Inman
* sIFR 1.0 by Mike Davidson, Shaun Inman and Tomas Jogin
* sIFR 2.0 by Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
See also and .
This software is licensed and provided under the CC-GNU LGPL.
See
*****************************************************************************/
var sIFR = new function() {
var self = this;
var ClassNames = {
ACTIVE : 'sIFR-active',
REPLACED : 'sIFR-replaced',
IGNORE : 'sIFR-ignore',
ALTERNATE : 'sIFR-alternate',
CLASS : 'sIFR-class',
LAYOUT : 'sIFR-layout',
FLASH : 'sIFR-flash',
FIX_FOCUS : 'sIFR-fixfocus',
DUMMY : 'sIFR-dummy'
};
ClassNames.IGNORE_CLASSES = [ClassNames.REPLACED, ClassNames.IGNORE, ClassNames.ALTERNATE];
this.MIN_FONT_SIZE = 6;
this.MAX_FONT_SIZE = 126;
this.FLASH_PADDING_BOTTOM = 5;
this.VERSION = '436';
this.isActive = false;
this.isEnabled = true;
this.fixHover = true;
this.autoInitialize = true;
this.setPrefetchCookie = true;
this.cookiePath = '/';
this.domains = [];
this.forceWidth = true;
this.fitExactly = false;
this.forceTextTransform = true;
this.useDomLoaded = true;
this.useStyleCheck = false;
this.hasFlashClassSet = false;
this.repaintOnResize = true;
this.replacements = [];
var elementCount = 0; // The number of replaced elements.
var isInitialized = false;
function Errors() {
this.fire = function(id) {
if(this[id + 'Alert']) alert(this[id + 'Alert']);
throw new Error(this[id]);
};
this.isFile = 'sIFR: Did not activate because the page is being loaded from the filesystem.';
this.isFileAlert = 'Hi!\n\nThanks for using sIFR on your page. Unfortunately sIFR couldn\'t activate, because it was loaded '
+ 'directly from your computer.\nDue to Flash security restrictions, you need to load sIFR through a web'
+ ' server.\n\nWe apologize for the inconvenience.';
};
function Util(sIFR) {
function capitalize($) {
return $.toLocaleUpperCase();
}
this.normalize = function(str) {
// Replace linebreaks and by whitespace, then normalize.
// Flash doesn't support no-breaking space characters, hence they're replaced by a normal space.
return str.replace(/\n|\r|\xA0/g, Util.SINGLE_WHITESPACE).replace(/\s+/g, Util.SINGLE_WHITESPACE);
};
this.textTransform = function(type, str) {
switch(type) {
case 'uppercase':
return str.toLocaleUpperCase();
case 'lowercase':
return str.toLocaleLowerCase();
case 'capitalize':
return str.replace(/^\w|\s\w/g, capitalize);
}
return str;
};
this.toHexString = function(str) {
if(str.charAt(0) != '#' || str.length != 4 && str.length != 7) return str;
str = str.substring(1);
return '0x' + (str.length == 3 ? str.replace(/(.)(.)(.)/, '$1$1$2$2$3$3') : str);
};
this.toJson = function(obj, strFunc) {
var json = '';
switch(typeof(obj)) {
case 'string':
json = '"' + strFunc(obj) + '"';
break;
case 'number':
case 'boolean':
json = obj.toString();
break;
case 'object':
json = [];
for(var prop in obj) {
if(obj[prop] == Object.prototype[prop]) continue;
json.push('"' + prop + '":' + this.toJson(obj[prop]));
}
json = '{' + json.join(',') + '}';
break;
}
return json;
};
this.convertCssArg = function(arg) {
if(!arg) return {};
if(typeof(arg) == 'object') {
if(arg.constructor == Array) arg = arg.join('');
else return arg;
}
var obj = {};
var rules = arg.split('}');
for(var i = 0; i < rules.length; i++) {
var $ = rules[i].match(/([^\s{]+)\s*\{(.+)\s*;?\s*/);
if(!$ || $.length != 3) continue;
if(!obj[$[1]]) obj[$[1]] = {};
var properties = $[2].split(';');
for(var j = 0; j < properties.length; j++) {
var $2 = properties[j].match(/\s*([^:\s]+)\s*\:\s*([^;]+)/);
if(!$2 || $2.length != 3) continue;
obj[$[1]][$2[1]] = $2[2].replace(/\s+$/, '');
}
}
return obj;
};
this.extractFromCss = function(css, selector, property, remove) {
var value = null;
if(css && css[selector] && css[selector][property]) {
value = css[selector][property];
if(remove) delete css[selector][property];
}
return value;
};
this.cssToString = function(arg) {
var css = [];
for(var selector in arg) {
var rule = arg[selector];
if(rule == Object.prototype[selector]) continue;
css.push(selector, '{');
for(var property in rule) {
if(rule[property] == Object.prototype[property]) continue;
var value = rule[property];
if(Util.UNIT_REMOVAL_PROPERTIES[property]) value = parseInt(value, 10);
css.push(property, ':', value, ';');
}
css.push('}');
}
return css.join('');
};
this.escape = function(str) {
return escape(str).replace(/\+/g, '%2B');
};
this.encodeVars = function(vars) {
return vars.join('&').replace(/%/g, '%25');
};
this.copyProperties = function(from, to) {
for(var property in from) {
if(to[property] === undefined) to[property] = from[property];
}
return to;
};
this.domain = function() {
var domain = '';
// When trying to access document.domain on a Google-translated page with Firebug, I got an exception.
// Try/catch to be safe.
try { domain = document.domain } catch(e) {};
return domain;
};
this.domainMatches = function(domain, match) {
if(match == '*' || match == domain) return true;
var wildcard = match.lastIndexOf('*');
if(wildcard > -1) {
match = match.substr(wildcard + 1);
var matchPosition = domain.lastIndexOf(match);
if(matchPosition > -1 && (matchPosition + match.length) == domain.length) return true;
}
return false;
};
this.uriEncode = function(s) {
return encodeURI(decodeURIComponent(s)); // Decode first, in case the URI was already encoded.
};
this.delay = function(ms, func, scope) {
var args = Array.prototype.slice.call(arguments, 3);
setTimeout(function() { func.apply(scope, args) }, ms);
};
};
Util.UNIT_REMOVAL_PROPERTIES = {leading: true, 'margin-left': true, 'margin-right': true, 'text-indent': true};
Util.SINGLE_WHITESPACE = ' ';
function DomUtil(sIFR) {
var self = this;
function getDimensionFromStyle(node, property, offsetProperty)
{
var dimension = self.getStyleAsInt(node, property, sIFR.ua.ie);
if(dimension == 0) {
dimension = node[offsetProperty];
for(var i = 3; i < arguments.length; i++) dimension -= self.getStyleAsInt(node, arguments[i], true);
}
return dimension;
}
this.getBody = function() {
return document.getElementsByTagName('body')[0] || null;
};
this.querySelectorAll = function(selector) {
return window.parseSelector(selector);
};
this.addClass = function(name, node) {
if(node) node.className = ((node.className || '') == '' ? '' : node.className + ' ') + name;
};
this.removeClass = function(name, node) {
if(node) node.className = node.className.replace(new RegExp('(^|\\s)' + name + '(\\s|$)'), '').replace(/^\s+|(\s)\s+/g, '$1');
};
this.hasClass = function(name, node) {
return new RegExp('(^|\\s)' + name + '(\\s|$)').test(node.className);
};
this.hasOneOfClassses = function(names, node) {
for(var i = 0; i < names.length; i++) {
if(this.hasClass(names[i], node)) return true;
}
return false;
};
this.ancestorHasClass = function(node, name) {
node = node.parentNode;
while(node && node.nodeType == 1) {
if(this.hasClass(name, node)) return true;
node = node.parentNode;
}
return false;
};
this.create = function(name, className) {
var node = document.createElementNS ? document.createElementNS(DomUtil.XHTML_NS, name) : document.createElement(name);
if(className) node.className = className;
return node;
};
this.getComputedStyle = function(node, property) {
var result;
if(document.defaultView && document.defaultView.getComputedStyle) {
var style = document.defaultView.getComputedStyle(node, null);
result = style ? style[property] : null;
} else {
if(node.currentStyle) result = node.currentStyle[property];
}
return result || ''; // Ensuring a string.
};
this.getStyleAsInt = function(node, property, requirePx) {
var value = this.getComputedStyle(node, property);
if(requirePx && !/px$/.test(value)) return 0;
return parseInt(value) || 0;
};
this.getWidthFromStyle = function(node) {
return getDimensionFromStyle(node, 'width', 'offsetWidth', 'paddingRight', 'paddingLeft', 'borderRightWidth', 'borderLeftWidth');
};
this.getHeightFromStyle = function(node) {
return getDimensionFromStyle(node, 'height', 'offsetHeight', 'paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth');
};
this.getDimensions = function(node) {
var width = node.offsetWidth;
var height = node.offsetHeight;
if(width == 0 || height == 0) {
for(var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
if(child.nodeType != 1) continue;
width = Math.max(width, child.offsetWidth);
height = Math.max(height, child.offsetHeight);
}
}
return {width: width, height: height};
};
this.getViewport = function() {
return {
width: window.innerWidth || document.documentElement.clientWidth || this.getBody().clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || this.getBody().clientHeight
};
};
this.blurElement = function(element) {
try {
element.blur();
return;
} catch(e) {};
// Move the focus to an input element, and then destroy it.
var input = this.create('input');
input.style.width = '0px';
input.style.height = '0px';
element.parentNode.appendChild(input);
input.focus();
input.blur();
input.parentNode.removeChild(input);
};
};
DomUtil.XHTML_NS = 'http://www.w3.org/1999/xhtml';
function UserAgentDetection(sIFR) {
var ua = navigator.userAgent.toLowerCase();
var product = (navigator.product || '').toLowerCase();
var platform = navigator.platform.toLowerCase();
this.parseVersion = UserAgentDetection.parseVersion;
this.macintosh = /^mac/.test(platform);
this.windows = /^win/.test(platform);
this.linux = /^linux/.test(platform);
this.quicktime = false;
this.opera = /opera/.test(ua);
this.konqueror = /konqueror/.test(ua);
this.ie = false/*@cc_on || true @*/;
this.ieSupported = this.ie && !/ppc|smartphone|iemobile|msie\s5\.5/.test(ua)/*@cc_on && @_jscript_version >= 5.5 @*/
this.ieWin = this.windows && this.ie/*@cc_on && @_jscript_version >= 5.1 @*/;
this.windows = this.windows && (!this.ie || this.ieWin);
this.ieMac = this.macintosh && this.ie/*@cc_on && @_jscript_version < 5.1 @*/;
this.macintosh = this.macintosh && (!this.ie || this.ieMac);
this.safari = /safari/.test(ua);
this.webkit = !this.konqueror && /applewebkit/.test(ua);
this.khtml = this.webkit || this.konqueror;
this.gecko = !this.khtml && product == 'gecko';
this.ieVersion = this.ie && /.*msie\s(\d\.\d)/.exec(ua) ? this.parseVersion(RegExp.$1) : '0';
this.operaVersion = this.opera && /.*opera(\s|\/)(\d+\.\d+)/.exec(ua) ? this.parseVersion(RegExp.$2) : '0';
this.webkitVersion = this.webkit && /.*applewebkit\/(\d+).*/.exec(ua) ? this.parseVersion(RegExp.$1) : '0';
this.geckoVersion = this.gecko && /.*rv:\s*([^\)]+)\)\s+gecko/.exec(ua) ? this.parseVersion(RegExp.$1) : '0';
this.konquerorVersion = this.konqueror && /.*konqueror\/([\d\.]+).*/.exec(ua) ? this.parseVersion(RegExp.$1) : '0';
this.flashVersion = 0;
if(this.ieWin) {
var axo;
var stop = false;
try {
axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7');
} catch(e) {
// In case the Flash 7 registry key does not exist, we need to test for specific
// Flash 6 installs before we can use the general key.
// See also .
// Many thanks to Geoff Stearns and Bobby van der Sluis for clarifying the problem and providing
// examples of non-crashing code.
try {
axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
this.flashVersion = this.parseVersion('6');
axo.AllowScriptAccess = 'always';
} catch(e) { stop = this.flashVersion == this.parseVersion('6'); }
if(!stop) try { axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); } catch(e) {}
}
if(!stop && axo) {
this.flashVersion = this.parseVersion((axo.GetVariable('$version') || '').replace(/^\D+(\d+)\D+(\d+)\D+(\d+).*/g, '$1.$2.$3'));
}
} else if(navigator.plugins && navigator.plugins['Shockwave Flash']) {
var d = navigator.plugins['Shockwave Flash'].description.replace(/^.*\s+(\S+\s+\S+$)/, '$1');
var v = d.replace(/^\D*(\d+\.\d+).*$/, '$1');
if(/r/.test(d)) v += d.replace(/^.*r(\d*).*$/, '.$1');
else if(/d/.test(d)) v += '.0';
this.flashVersion = this.parseVersion(v);
// Watch out for QuickTime, which could be stealing the Flash handling! Also check to make sure the plugin for the Flash
// MIMEType is enabled.
var foundEnabled = false;
for(var i = 0, valid = this.flashVersion >= UserAgentDetection.MIN_FLASH_VERSION; valid && i < navigator.mimeTypes.length; i++) {
var mime = navigator.mimeTypes[i];
if(mime.type != 'application/x-shockwave-flash') continue;
if(mime.enabledPlugin) {
foundEnabled = true;
if(mime.enabledPlugin.description.toLowerCase().indexOf('quicktime') > -1) {
valid = false;
this.quicktime = true;
}
}
}
if(this.quicktime || !foundEnabled) this.flashVersion = this.parseVersion('0');
}
this.flash = this.flashVersion >= UserAgentDetection.MIN_FLASH_VERSION;
this.transparencySupport = this.macintosh || this.windows
|| this.linux && (
this.flashVersion >= this.parseVersion('10')
&& (
this.gecko && this.geckoVersion >= this.parseVersion('1.9')
|| this.opera
)
);
this.computedStyleSupport = this.ie || !!document.defaultView.getComputedStyle;
this.fixFocus = this.gecko && this.windows;
this.nativeDomLoaded = this.gecko || this.webkit && this.webkitVersion >= this.parseVersion('525')
|| this.konqueror && this.konquerorMajor > this.parseVersion('03') || this.opera;
this.mustCheckStyle = this.khtml || this.opera;
this.forcePageLoad = this.webkit && this.webkitVersion < this.parseVersion('523')
this.properDocument = typeof(document.location) == 'object';
this.supported = this.flash && this.properDocument && (!this.ie || this.ieSupported) && this.computedStyleSupport
&& (!this.opera || this.operaVersion >= this.parseVersion('9.61'))
&& (!this.webkit || this.webkitVersion >= this.parseVersion('412'))
&& (!this.gecko || this.geckoVersion >= this.parseVersion('1.8.0.12'))
&& (!this.konqueror/* || this.konquerorVersion >= this.parseVersion('4.1')*/);
};
UserAgentDetection.parseVersion = function(s) {
return s.replace(
/(^|\D)(\d+)(?=\D|$)/g,
function(s, nonDigit, digits) {
s = nonDigit;
for(var i = 4 - digits.length; i >= 0; i--) s += '0';
return s + digits;
}
);
};
UserAgentDetection.MIN_FLASH_VERSION = UserAgentDetection.parseVersion('8');
function FragmentIdentifier(sIFR) {
this.fix = sIFR.ua.ieWin && window.location.hash != '';
var cachedTitle;
this.cache = function() {
cachedTitle = document.title;
};
function doFix() {
document.title = cachedTitle;
}
this.restore = function() {
if(this.fix) setTimeout(doFix, 0);
};
};
function PageLoad(sIFR) {
var dummy = null;
function pollLoad() {
try {
// IE hack courtesy of Diego Perini – .
// Merged polling taken from jQuery –
if(sIFR.ua.ie || document.readyState != 'loaded' && document.readyState != 'complete') {
document.documentElement.doScroll('left');
}
} catch(e) {
return setTimeout(pollLoad, 10);
}
afterDomLoad();
};
function afterDomLoad() {
if(sIFR.useStyleCheck) checkStyle();
else if(!sIFR.ua.mustCheckStyle) fire(null, true);
};
function checkStyle() {
dummy = sIFR.dom.create("div", ClassNames.DUMMY);
sIFR.dom.getBody().appendChild(dummy);
pollStyle();
};
function pollStyle() {
if(sIFR.dom.getComputedStyle(dummy, 'marginLeft') == '42px') afterStyle();
else setTimeout(pollStyle, 10);
};
function afterStyle() {
if(dummy && dummy.parentNode) dummy.parentNode.removeChild(dummy);
dummy = null;
fire(null, true);
};
function fire(evt, preserveReplacements) {
sIFR.initialize(preserveReplacements);
// Remove handlers to prevent memory leak in Firefox 1.5, but only after onload.
if(evt && evt.type == 'load') {
if(document.removeEventListener) document.removeEventListener('DOMContentLoaded', fire, false);
if(window.removeEventListener) window.removeEventListener('load', fire, false);
}
};
// Unload detection based on the research from Moxiecode.
function verifyUnload() {
sIFR.prepareClearReferences();
if(document.readyState == 'interactive') {
document.attachEvent('onstop', unloadByStop);
setTimeout(function() { document.detachEvent('onstop', unloadByStop) }, 0);
}
};
function unloadByStop() {
document.detachEvent('onstop', unloadByStop);
fireUnload();
};
function fireUnload() {
sIFR.clearReferences();
};
this.attach = function() {
if(window.addEventListener) window.addEventListener('load', fire, false);
else window.attachEvent('onload', fire);
if(!sIFR.useDomLoaded || sIFR.ua.forcePageLoad || sIFR.ua.ie && window.top != window) return;
if(sIFR.ua.nativeDomLoaded) {
document.addEventListener('DOMContentLoaded', afterDomLoad, false);
} else if(sIFR.ua.ie || sIFR.ua.khtml) {
pollLoad();
}
};
this.attachUnload = function() {
if(!sIFR.ua.ie) return;
window.attachEvent('onbeforeunload', verifyUnload);
window.attachEvent('onunload', fireUnload);
}
};
var PREFETCH_COOKIE = 'sifrFetch';
function Prefetch(sIFR) {
var hasPrefetched = false;
this.fetchMovies = function(movies) {
if(sIFR.setPrefetchCookie && new RegExp(';?' + PREFETCH_COOKIE + '=true;?').test(document.cookie)) return;
try { // We don't know which DOM actions the user agent will allow
hasPrefetched = true;
prefetch(movies);
} catch(e) {}
if(sIFR.setPrefetchCookie) document.cookie = PREFETCH_COOKIE + '=true;path=' + sIFR.cookiePath;
};
this.clear = function() {
if(!hasPrefetched) return;
try {
var nodes = document.getElementsByTagName('script');
for(var i = nodes.length - 1; i >= 0; i--) {
var node = nodes[i];
if(node.type == 'sifr/prefetch') node.parentNode.removeChild(node);
}
} catch(e) {}
};
function prefetch(args) {
for(var i = 0; i < args.length; i++) {
document.write('' + 'script>');
}
}
};
function BrokenFlashIE(sIFR) {
var active = sIFR.ua.ie;
var fixFlash = active && sIFR.ua.flashVersion < sIFR.ua.parseVersion('9.0.115');
var resetMovies = {};
var registry = {};
this.fixFlash = fixFlash;
this.register = function(flashNode) {
if(!active) return;
var id = flashNode.getAttribute('id');
// Try cleaning up previous Flash