Enjoy unlimited access to all forum features for FREE! Optional upgrade available for extra perks.

IE9 Cufon / Prettyphoto Problem

Status
Not open for further replies.
Joined
Feb 23, 2011
Posts
740
Reaction score
16
For any other developers out there that may use Cufon font replacement or the Prettyphoto lightbox (as I do) then be aware of compatablility problems with IE9 with both codesets.

It seems after 9 attempts Microsoft still cannot get a browser right which is very frustrating as the IE9 automatic update is rolling out now across windows versions with AU's turned on.

The Cufon problem only occurs with websites using a cufon-yui.js older than about 2 months, so if your site was built very recently there shouldn't be a problem. The same applies to prettyphoto.

The problem amounts to your Cufon fonts simply not being visible in IE9 at all (which many developers or site owners may not realise).

To solve this issue:
Prettyphoto: No need to replace the call files, simply replace the Prettyphoto JS files
Cufon: Replace the code in your cufon-yui.js with the following code:

var Cufon = (function() {

var api = function() {
return api.replace.apply(null, arguments);
};

var DOM = api.DOM = {

ready: (function() {

var complete = false, readyStatus = { loaded: 1, complete: 1 };

var queue = [], perform = function() {
if (complete) return;
complete = true;
for (var fn; fn = queue.shift(); fn());
};

// Gecko, Opera, WebKit r26101+

if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', perform, false);
window.addEventListener('pageshow', perform, false); // For cached Gecko pages
}

// Old WebKit, Internet Explorer

if (!window.opera && document.readyState) (function() {
readyStatus[document.readyState] ? perform() : setTimeout(arguments.callee, 10);
})();

// Internet Explorer

if (document.readyState && document.createStyleSheet) (function() {
try {
document.body.doScroll('left');
perform();
}
catch (e) {
setTimeout(arguments.callee, 1);
}
})();

addEvent(window, 'load', perform); // Fallback

return function(listener) {
if (!arguments.length) perform();
else complete ? listener() : queue.push(listener);
};

})(),

root: function() {
return document.documentElement || document.body;
},

strict: (function() {
var doctype;
// no doctype (doesn't always catch it though.. IE I'm looking at you)
if (document.compatMode == 'BackCompat') return false;
// WebKit, Gecko, Opera, IE9+
doctype = document.doctype;
if (doctype) {
return !/frameset|transitional/i.test(doctype.publicId);
}
// IE<9, firstChild is the doctype even if there's an XML declaration
doctype = document.firstChild;
if (doctype.nodeType != 8 || /^DOCTYPE.+(transitional|frameset)/i.test(doctype.data)) {
return false;
}
return true;
})()

};

var CSS = api.CSS = {

Size: function(value, base) {

this.value = parseFloat(value);
this.unit = String(value).match(/[a-z%]*$/)[0] || 'px';

this.convert = function(value) {
return value / base * this.value;
};

this.convertFrom = function(value) {
return value / this.value * base;
};

this.toString = function() {
return this.value + this.unit;
};

},

addClass: function(el, className) {
var current = el.className;
el.className = current + (current && ' ') + className;
return el;
},

color: cached(function(value) {
var parsed = {};
parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) {
parsed.opacity = parseFloat($2);
return 'rgb(' + $1 + ')';
});
return parsed;
}),

// has no direct CSS equivalent.
// @see http://msdn.microsoft.com/en-us/library/system.windows.fontstretches.aspx
fontStretch: cached(function(value) {
if (typeof value == 'number') return value;
if (/%$/.test(value)) return parseFloat(value) / 100;
return {
'ultra-condensed': 0.5,
'extra-condensed': 0.625,
condensed: 0.75,
'semi-condensed': 0.875,
'semi-expanded': 1.125,
expanded: 1.25,
'extra-expanded': 1.5,
'ultra-expanded': 2
}[value] || 1;
}),

getStyle: function(el) {
var view = document.defaultView;
if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null));
if (el.currentStyle) return new Style(el.currentStyle);
return new Style(el.style);
},

gradient: cached(function(value) {
var gradient = {
id: value,
type: value.match(/^-([a-z]+)-gradient\(/)[1],
stops: []
}, colors = value.substr(value.indexOf('(')).match(/([\d.]+=)?(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)/ig);
for (var i = 0, l = colors.length, stop; i < l; ++i) {
stop = colors.split('=', 2).reverse();
gradient.stops.push([ stop[1] || i / (l - 1), stop[0] ]);
}
return gradient;
}),

quotedList: cached(function(value) {
// doesn't work properly with empty quoted strings (""), but
// it's not worth the extra code.
var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match;
while (match = re.exec(value)) list.push(match[3] || match[1]);
return list;
}),

recognizesMedia: cached(function(media) {
var el = document.createElement('style'), sheet, container, supported;
el.type = 'text/css';
el.media = media;
try { // this is cached anyway
el.appendChild(document.createTextNode('/**/'));
} catch (e) {}
container = elementsByTagName('head')[0];
container.insertBefore(el, container.firstChild);
sheet = (el.sheet || el.styleSheet);
supported = sheet && !sheet.disabled;
container.removeChild(el);
return supported;
}),

removeClass: function(el, className) {
var re = RegExp('(?:^|\\s+)' + className + '(?=\\s|$)', 'g');
el.className = el.className.replace(re, '');
return el;
},

supports: function(property, value) {
var checker = document.createElement('span').style;
if (checker[property] === undefined) return false;
checker[property] = value;
return checker[property] === value;
},

textAlign: function(word, style, position, wordCount) {
if (style.get('textAlign') == 'right') {
if (position > 0) word = ' ' + word;
}
else if (position < wordCount - 1) word += ' ';
return word;
},

textShadow: cached(function(value) {
if (value == 'none') return null;
var shadows = [], currentShadow = {}, result, offCount = 0;
var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;
while (result = re.exec(value)) {
if (result[0] == ',') {
shadows.push(currentShadow);
currentShadow = {};
offCount = 0;
}
else if (result[1]) {
currentShadow.color = result[1];
}
else {
currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2];
}
}
shadows.push(currentShadow);
return shadows;
}),

textTransform: (function() {
var map = {
uppercase: function(s) {
return s.toUpperCase();
},
lowercase: function(s) {
return s.toLowerCase();
},
capitalize: function(s) {
return s.replace(/(?:^|\s)./g, function($0) {
return $0.toUpperCase();
});
}
};
return function(text, style) {
var transform = map[style.get('textTransform')];
return transform ? transform(text) : text;
};
})(),

whiteSpace: (function() {
var ignore = {
inline: 1,
'inline-block': 1,
'run-in': 1
};
var wsStart = /^\s+/, wsEnd = /\s+$/;
return function(text, style, node, previousElement, simple) {
if (simple) return text.replace(wsStart, '').replace(wsEnd, ''); // @fixme too simple
if (previousElement) {
if (previousElement.nodeName.toLowerCase() == 'br') {
text = text.replace(wsStart, '');
}
}
if (ignore[style.get('display')]) return text;
if (!node.previousSibling) text = text.replace(wsStart, '');
if (!node.nextSibling) text = text.replace(wsEnd, '');
return text;
};
})()

};

CSS.ready = (function() {

// don't do anything in Safari 2 (it doesn't recognize any media type)
var complete = !CSS.recognizesMedia('all'), hasLayout = false;

var queue = [], perform = function() {
complete = true;
for (var fn; fn = queue.shift(); fn());
};

var links = elementsByTagName('link'), styles = elementsByTagName('style');

var checkTypes = {
'': 1,
'text/css': 1
};

function isContainerReady(el) {
if (!checkTypes[el.type.toLowerCase()]) return true;
return el.disabled || isSheetReady(el.sheet, el.media || 'screen');
}

function isSheetReady(sheet, media) {
// in Opera sheet.disabled is true when it's still loading,
// even though link.disabled is false. they stay in sync if
// set manually.
if (!CSS.recognizesMedia(media || 'all')) return true;
if (!sheet || sheet.disabled) return false;
try {
var rules = sheet.cssRules, rule;
if (rules) {
// needed for Safari 3 and Chrome 1.0.
// in standards-conforming browsers cssRules contains @-rules.
// Chrome 1.0 weirdness: rules[<number larger than .length - 1>]
// returns the last rule, so a for loop is the only option.
search: for (var i = 0, l = rules.length; rule = rules, i < l; ++i) {
switch (rule.type) {
case 2: // @charset
break;
case 3: // @import
if (!isSheetReady(rule.styleSheet, rule.media.mediaText)) return false;
break;
default:
// only @charset can precede @import
break search;
}
}
}
}
catch (e) {} // probably a style sheet from another domain
return true;
}

function allStylesLoaded() {
// Internet Explorer's style sheet model, there's no need to do anything
if (document.createStyleSheet) return true;
// standards-compliant browsers
var el, i;
for (i = 0; el = links; ++i) {
if (el.rel.toLowerCase() == 'stylesheet' && !isContainerReady(el)) return false;
}
for (i = 0; el = styles; ++i) {
if (!isContainerReady(el)) return false;
}
return true;
}

DOM.ready(function() {
// getComputedStyle returns null in Gecko if used in an iframe with display: none
if (!hasLayout) hasLayout = CSS.getStyle(document.body).isUsable();
if (complete || (hasLayout && allStylesLoaded())) perform();
else setTimeout(arguments.callee, 10);
});

return function(listener) {
if (complete) listener();
else queue.push(listener);
};

})();

function Font(data) {

var face = this.face = data.face, wordSeparators = {
'\u0020': 1,
'\u00a0': 1,
'\u3000': 1
};

this.glyphs = (function(glyphs) {
var key, fallbacks = {
'\u2011': '\u002d',
'\u00ad': '\u2011'
};
for (key in fallbacks) {
if (!hasOwnProperty(fallbacks, key)) continue;
if (!glyphs[key]) glyphs[key] = glyphs[fallbacks[key]];
}
return glyphs;
})(data.glyphs);

this.w = data.w;
this.baseSize = parseInt(face['units-per-em'], 10);

this.family = face['font-family'].toLowerCase();
this.weight = face['font-weight'];
this.style = face['font-style'] || 'normal';

this.viewBox = (function () {
var parts = face.bbox.split(/\s+/);
var box = {
minX: parseInt(parts[0], 10),
minY: parseInt(parts[1], 10),
maxX: parseInt(parts[2], 10),
maxY: parseInt(parts[3], 10)
};
box.width = box.maxX - box.minX;
box.height = box.maxY - box.minY;
box.toString = function() {
return [ this.minX, this.minY, this.width, this.height ].join(' ');
};
return box;
})();

this.ascent = -parseInt(face.ascent, 10);
this.descent = -parseInt(face.descent, 10);

this.height = -this.ascent + this.descent;

this.spacing = function(chars, letterSpacing, wordSpacing) {
var glyphs = this.glyphs, glyph,
kerning, k,
jumps = [],
width = 0, w,
i = -1, j = -1, chr;
while (chr = chars[++i]) {
glyph = glyphs[chr] || this.missingGlyph;
if (!glyph) continue;
if (kerning) {
width -= k = kerning[chr] || 0;
jumps[j] -= k;
}
w = glyph.w;
if (isNaN(w)) w = +this.w; // may have been a String in old fonts
if (w > 0) {
w += letterSpacing;
if (wordSeparators[chr]) w += wordSpacing;
}
width += jumps[++j] = ~~w; // get rid of decimals
kerning = glyph.k;
}
jumps.total = width;
return jumps;
};

}

function FontFamily() {

var styles = {}, mapping = {
oblique: 'italic',
italic: 'oblique'
};

this.add = function(font) {
(styles[font.style] || (styles[font.style] = {}))[font.weight] = font;
};

this.get = function(style, weight) {
var weights = styles[style] || styles[mapping[style]]
|| styles.normal || styles.italic || styles.oblique;
if (!weights) return null;
// we don't have to worry about "bolder" and "lighter"
// because IE's currentStyle returns a numeric value for it,
// and other browsers use the computed value anyway
weight = {
normal: 400,
bold: 700
}[weight] || parseInt(weight, 10);
if (weights[weight]) return weights[weight];
// http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight
// Gecko uses x99/x01 for lighter/bolder
var up = {
1: 1,
99: 0
}[weight % 100], alts = [], min, max;
if (up === undefined) up = weight > 400;
if (weight == 500) weight = 400;
for (var alt in weights) {
if (!hasOwnProperty(weights, alt)) continue;
alt = parseInt(alt, 10);
if (!min || alt < min) min = alt;
if (!max || alt > max) max = alt;
alts.push(alt);
}
if (weight < min) weight = min;
if (weight > max) weight = max;
alts.sort(function(a, b) {
return (up
? (a >= weight && b >= weight) ? a < b : a > b
: (a <= weight && b <= weight) ? a > b : a < b) ? -1 : 1;
});
return weights[alts[0]];
};

}

function HoverHandler() {

function contains(node, anotherNode) {
try {
if (node.contains) return node.contains(anotherNode);
return node.compareDocumentPosition(anotherNode) & 16;
}
catch(e) {} // probably a XUL element such as a scrollbar
return false;
}

// mouseover/mouseout (standards) mode
function onOverOut(e) {
var related = e.relatedTarget;
// there might be no relatedTarget if the element is right next
// to the window frame
if (related && contains(this, related)) return;
trigger(this, e.type == 'mouseover');
}

// mouseenter/mouseleave (probably ie) mode
function onEnterLeave(e) {
if (!e) e = window.event;
// ie model, we don't have access to "this", but
// mouseenter/leave doesn't bubble so it's fine.
trigger(e.target || e.srcElement, e.type == 'mouseenter');
}

function trigger(el, hoverState) {
// A timeout is needed so that the event can actually "happen"
// before replace is triggered. This ensures that styles are up
// to date.
setTimeout(function() {
var options = sharedStorage.get(el).options;
if (hoverState) {
options = merge(options, options.hover);
options._mediatorMode = 1;
}
api.replace(el, options, true);
}, 10);
}

this.attach = function(el) {
if (el.onmouseenter === undefined) {
addEvent(el, 'mouseover', onOverOut);
addEvent(el, 'mouseout', onOverOut);
}
else {
addEvent(el, 'mouseenter', onEnterLeave);
addEvent(el, 'mouseleave', onEnterLeave);
}
};

this.detach = function(el) {
if (el.onmouseenter === undefined) {
removeEvent(el, 'mouseover', onOverOut);
removeEvent(el, 'mouseout', onOverOut);
}
else {
removeEvent(el, 'mouseenter', onEnterLeave);
removeEvent(el, 'mouseleave', onEnterLeave);
}
};

}

function ReplaceHistory() {

var list = [], map = {};

function filter(keys) {
var values = [], key;
for (var i = 0; key = keys; ++i) values = list[map[key]];
return values;
}

this.add = function(key, args) {
map[key] = list.push(args) - 1;
};

this.repeat = function() {
var snapshot = arguments.length ? filter(arguments) : list, args;
for (var i = 0; args = snapshot[i++];) api.replace(args[0], args[1], true);
};

}

function Storage() {

var map = {}, at = 0;

function identify(el) {
return el.cufid || (el.cufid = ++at);
}

this.get = function(el) {
var id = identify(el);
return map[id] || (map[id] = {});
};

}

function Style(style) {

var custom = {}, sizes = {};

this.extend = function(styles) {
for (var property in styles) {
if (hasOwnProperty(styles, property)) custom[property] = styles[property];
}
return this;
};

this.get = function(property) {
return custom[property] != undefined ? custom[property] : style[property];
};

this.getSize = function(property, base) {
return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base));
};

this.isUsable = function() {
return !!style;
};

}

function addEvent(el, type, listener) {
if (el.addEventListener) {
el.addEventListener(type, listener, false);
}
else if (el.attachEvent) {
// we don't really need "this" right now, saves code
el.attachEvent('on' + type, listener);
}
}

function attach(el, options) {
if (options._mediatorMode) return el;
var storage = sharedStorage.get(el);
var oldOptions = storage.options;
if (oldOptions) {
if (oldOptions === options) return el;
if (oldOptions.hover) hoverHandler.detach(el);
}
if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) {
hoverHandler.attach(el);
}
storage.options = options;
return el;
}

function cached(fun) {
var cache = {};
return function(key) {
if (!hasOwnProperty(cache, key)) cache[key] = fun.apply(null, arguments);
return cache[key];
};
}

function getFont(el, style) {
var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family;
for (var i = 0; family = families; ++i) {
if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight'));
}
return null;
}

function elementsByTagName(query) {
return document.getElementsByTagName(query);
}

function hasOwnProperty(obj, property) {
return obj.hasOwnProperty(property);
}

function merge() {
var merged = {}, arg, key;
for (var i = 0, l = arguments.length; arg = arguments, i < l; ++i) {
for (key in arg) {
if (hasOwnProperty(arg, key)) merged[key] = arg[key];
}
}
return merged;
}

function process(font, text, style, options, node, el) {
var fragment = document.createDocumentFragment(), processed;
if (text === '') return fragment;
var separate = options.separate;
var parts = text.split(separators[separate]), needsAligning = (separate == 'words');
if (needsAligning && HAS_BROKEN_REGEXP) {
// @todo figure out a better way to do this
if (/^\s/.test(text)) parts.unshift('');
if (/\s$/.test(text)) parts.push('');
}
for (var i = 0, l = parts.length; i < l; ++i) {
processed = engines[options.engine](font,
needsAligning ? CSS.textAlign(parts, style, i, l) : parts,
style, options, node, el, i < l - 1);
if (processed) fragment.appendChild(processed);
}
return fragment;
}

function removeEvent(el, type, listener) {
if (el.removeEventListener) {
el.removeEventListener(type, listener, false);
}
else if (el.detachEvent) {
el.detachEvent('on' + type, listener);
}
}

function replaceElement(el, options) {
var name = el.nodeName.toLowerCase();
if (options.ignore[name]) return;
if (options.ignoreClass && options.ignoreClass.test(el.className)) return;
if (options.onBeforeReplace) options.onBeforeReplace(el, options);
var replace = !options.textless[name], simple = (options.trim === 'simple');
var style = CSS.getStyle(attach(el, options)).extend(options);
// may cause issues if the element contains other elements
// with larger fontSize, however such cases are rare and can
// be fixed by using a more specific selector
if (parseFloat(style.get('fontSize')) === 0) return;
var font = getFont(el, style), node, type, next, anchor, text, lastElement;
var isShy = options.softHyphens, anyShy = false, pos, shy, reShy = /\u00ad/g;
var modifyText = options.modifyText;
if (!font) return;
for (node = el.firstChild; node; node = next) {
type = node.nodeType;
next = node.nextSibling;
if (replace && type == 3) {
if (isShy && el.nodeName.toLowerCase() != TAG_SHY) {
pos = node.data.indexOf('\u00ad');
if (pos >= 0) {
node.splitText(pos);
next = node.nextSibling;
next.deleteData(0, 1);
shy = document.createElement(TAG_SHY);
shy.appendChild(document.createTextNode('\u00ad'));
el.insertBefore(shy, next);
next = shy;
anyShy = true;
}
}
// Node.normalize() is broken in IE 6, 7, 8
if (anchor) {
anchor.appendData(node.data);
el.removeChild(node);
}
else anchor = node;
if (next) continue;
}
if (anchor) {
text = anchor.data;
if (!isShy) text = text.replace(reShy, '');
text = CSS.whiteSpace(text, style, anchor, lastElement, simple);
// modify text only on the first replace
if (modifyText) text = modifyText(text, anchor, el, options);
el.replaceChild(process(font, text, style, options, node, el), anchor);
anchor = null;
}
if (type == 1) {
if (node.firstChild) {
if (node.nodeName.toLowerCase() == 'cufon') {
engines[options.engine](font, null, style, options, node, el);
}
else arguments.callee(node, options);
}
lastElement = node;
}
}
if (isShy && anyShy) {
updateShy(el);
if (!trackingShy) addEvent(window, 'resize', updateShyOnResize);
trackingShy = true;
}
if (options.onAfterReplace) options.onAfterReplace(el, options);
}

function updateShy(context) {
var shys, shy, parent, glue, newGlue, next, prev, i;
shys = context.getElementsByTagName(TAG_SHY);
// unfortunately there doesn't seem to be any easy
// way to avoid having to loop through the shys twice.
for (i = 0; shy = shys; ++i) {
shy.className = C_SHY_DISABLED;
glue = parent = shy.parentNode;
if (glue.nodeName.toLowerCase() != TAG_GLUE) {
newGlue = document.createElement(TAG_GLUE);
newGlue.appendChild(shy.previousSibling);
parent.insertBefore(newGlue, shy);
newGlue.appendChild(shy);
}
else {
// get rid of double glue (edge case fix)
glue = glue.parentNode;
if (glue.nodeName.toLowerCase() == TAG_GLUE) {
parent = glue.parentNode;
while (glue.firstChild) {
parent.insertBefore(glue.firstChild, glue);
}
parent.removeChild(glue);
}
}
}
for (i = 0; shy = shys; ++i) {
shy.className = '';
glue = shy.parentNode;
parent = glue.parentNode;
next = glue.nextSibling || parent.nextSibling;
// make sure we're comparing same types
prev = (next.nodeName.toLowerCase() == TAG_GLUE) ? glue : shy.previousSibling;
if (prev.offsetTop >= next.offsetTop) {
shy.className = C_SHY_DISABLED;
if (prev.offsetTop < next.offsetTop) {
// we have an annoying edge case, double the glue
newGlue = document.createElement(TAG_GLUE);
parent.insertBefore(newGlue, glue);
newGlue.appendChild(glue);
newGlue.appendChild(next);
}
}
}
}

function updateShyOnResize() {
if (ignoreResize) return; // needed for IE
CSS.addClass(DOM.root(), C_VIEWPORT_RESIZING);
clearTimeout(shyTimer);
shyTimer = setTimeout(function() {
ignoreResize = true;
CSS.removeClass(DOM.root(), C_VIEWPORT_RESIZING);
updateShy(document);
ignoreResize = false;
}, 100);
}

var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0;
var TAG_GLUE = 'cufonglue';
var TAG_SHY = 'cufonshy';
var C_SHY_DISABLED = 'cufon-shy-disabled';
var C_VIEWPORT_RESIZING = 'cufon-viewport-resizing';

var sharedStorage = new Storage();
var hoverHandler = new HoverHandler();
var replaceHistory = new ReplaceHistory();
var initialized = false;
var trackingShy = false;
var shyTimer;
var ignoreResize = false;

var engines = {}, fonts = {}, defaultOptions = {
autoDetect: false,
engine: null,
forceHitArea: false,
hover: false,
hoverables: {
a: true
},
ignore: {
applet: 1,
canvas: 1,
col: 1,
colgroup: 1,
head: 1,
iframe: 1,
map: 1,
noscript: 1,
optgroup: 1,
option: 1,
script: 1,
select: 1,
style: 1,
textarea: 1,
title: 1,
pre: 1
},
ignoreClass: null,
modifyText: null,
onAfterReplace: null,
onBeforeReplace: null,
printable: true,
selector: (
window.Sizzle
|| (window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues
|| (window.dojo && dojo.query)
|| (window.glow && glow.dom && glow.dom.get)
|| (window.Ext && Ext.query)
|| (window.YAHOO && YAHOO.util && YAHOO.util.Selector && YAHOO.util.Selector.query)
|| (window.$$ && function(query) { return $$(query); })
|| (window.$ && function(query) { return $(query); })
|| (document.querySelectorAll && function(query) { return document.querySelectorAll(query); })
|| elementsByTagName
),
separate: 'words', // 'none' and 'characters' are also accepted
softHyphens: true,
textless: {
dl: 1,
html: 1,
ol: 1,
table: 1,
tbody: 1,
thead: 1,
tfoot: 1,
tr: 1,
ul: 1
},
textShadow: 'none',
trim: 'advanced'
};

var separators = {
// The first pattern may cause unicode characters above
// code point 255 to be removed in Safari 3.0. Luckily enough
// Safari 3.0 does not include non-breaking spaces in \s, so
// we can just use a simple alternative pattern.
words: /\s/.test('\u00a0') ? /[^\S\u00a0]+/ : /\s+/,
characters: '',
none: /^/
};

api.now = function() {
DOM.ready();
return api;
};

api.refresh = function() {
replaceHistory.repeat.apply(replaceHistory, arguments);
return api;
};

api.registerEngine = function(id, engine) {
if (!engine) return api;
engines[id] = engine;
return api.set('engine', id);
};

api.registerFont = function(data) {
if (!data) return api;
var font = new Font(data), family = font.family;
if (!fonts[family]) fonts[family] = new FontFamily();
fonts[family].add(font);
return api.set('fontFamily', '"' + family + '"');
};

api.replace = function(elements, options, ignoreHistory) {
options = merge(defaultOptions, options);
if (!options.engine) return api; // there's no browser support so we'll just stop here
if (!initialized) {
CSS.addClass(DOM.root(), 'cufon-active cufon-loading');
CSS.ready(function() {
// fires before any replace() calls, but it doesn't really matter
CSS.addClass(CSS.removeClass(DOM.root(), 'cufon-loading'), 'cufon-ready');
});
initialized = true;
}
if (options.hover) options.forceHitArea = true;
if (options.autoDetect) delete options.fontFamily;
if (typeof options.ignoreClass == 'string') {
options.ignoreClass = new RegExp('(?:^|\\s)(?:' + options.ignoreClass.replace(/\s+/g, '|') + ')(?:\\s|$)');
}
if (typeof options.textShadow == 'string') {
options.textShadow = CSS.textShadow(options.textShadow);
}
if (typeof options.color == 'string' && /^-/.test(options.color)) {
options.textGradient = CSS.gradient(options.color);
}
else delete options.textGradient;
if (typeof elements == 'string') {
if (!ignoreHistory) replaceHistory.add(elements, arguments);
elements = [ elements ];
}
else if (elements.nodeType) elements = [ elements ];
CSS.ready(function() {
for (var i = 0, l = elements.length; i < l; ++i) {
var el = elements;
if (typeof el == 'string') api.replace(options.selector(el), options, true);
else replaceElement(el, options);
}
});
return api;
};

api.set = function(option, value) {
defaultOptions[option] = value;
return api;
};

return api;

})();

Cufon.registerEngine('vml', (function() {

var ns = document.namespaces;
if (!ns) return;
ns.add('cvml', 'urn:schemas-microsoft-com:vml');
ns = null;

var check = document.createElement('cvml:shape');
check.style.behavior = 'url(#default#VML)';
if (!check.coordsize) return; // VML isn't supported
check = null;

var HAS_BROKEN_LINEHEIGHT = (document.documentMode || 0) < 8;

document.write(('<style type="text/css">' +
'cufoncanvas{text-indent:0;}' +
'@media screen{' +
'cvml\\:shape,cvml\\:rect,cvml\\:fill,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute;}' +
'cufoncanvas{position:absolute;text-align:left;}' +
'cufon{display:inline-block;position:relative;vertical-align:' +
(HAS_BROKEN_LINEHEIGHT
? 'middle'
: 'text-bottom') +
';}' +

'cufon cufontext{position:absolute;left:-10000in;font-size:1px;text-align:left;}' +
'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy{display:none;}' +
'cufonglue{white-space:nowrap;display:inline-block;}' +
'.cufon-viewport-resizing cufonglue{white-space:normal;}' +
'a cufon{cursor:pointer}' + // ignore !important here
'}' +
'@media print{' +
'cufon cufoncanvas{display:none;}' +
'}' +
'</style>').replace(/;/g, '!important;'));

function getFontSizeInPixels(el, value) {
return getSizeInPixels(el, /(?:em|ex|%)$|^[a-z-]+$/i.test(value) ? '1em' : value);
}

// Original by Dead Edwards.
// Combined with getFontSizeInPixels it also works with relative units.
function getSizeInPixels(el, value) {
if (!isNaN(value) || /px$/i.test(value)) return parseFloat(value);
var style = el.style.left, runtimeStyle = el.runtimeStyle.left;
el.runtimeStyle.left = el.currentStyle.left;
el.style.left = value.replace('%', 'em');
var result = el.style.pixelLeft;
el.style.left = style;
el.runtimeStyle.left = runtimeStyle;
return result;
}

function getSpacingValue(el, style, size, property) {
var key = 'computed' + property, value = style[key];
if (isNaN(value)) {
value = style.get(property);
style[key] = value = (value == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, value));
}
return value;
}

var fills = {};

function gradientFill(gradient) {
var id = gradient.id;
if (!fills[id]) {
var stops = gradient.stops, fill = document.createElement('cvml:fill'), colors = [];
fill.type = 'gradient';
fill.angle = 180;
fill.focus = '0';
fill.method = 'none';
fill.color = stops[0][1];
for (var j = 1, k = stops.length - 1; j < k; ++j) {
colors.push(stops[j][0] * 100 + '% ' + stops[j][1]);
}
fill.colors = colors.join(',');
fill.color2 = stops[k][1];
fills[id] = fill;
}
return fills[id];
}

return function(font, text, style, options, node, el, hasNext) {

var redraw = (text === null);

if (redraw) text = node.alt;

var viewBox = font.viewBox;

var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));

var wrapper, canvas;

if (redraw) {
wrapper = node;
canvas = node.firstChild;
}
else {
wrapper = document.createElement('cufon');
wrapper.className = 'cufon cufon-vml';
wrapper.alt = text;

canvas = document.createElement('cufoncanvas');
wrapper.appendChild(canvas);

if (options.printable) {
var print = document.createElement('cufontext');
print.appendChild(document.createTextNode(text));
wrapper.appendChild(print);
}

// ie6, for some reason, has trouble rendering the last VML element in the document.
// we can work around this by injecting a dummy element where needed.
// @todo find a better solution
if (!hasNext) wrapper.appendChild(document.createElement('cvml:shape'));
}

var wStyle = wrapper.style;
var cStyle = canvas.style;

var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height);
var roundingFactor = roundedHeight / height;
var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
var minX = viewBox.minX, minY = viewBox.minY;

cStyle.height = roundedHeight;
cStyle.top = Math.round(size.convert(minY - font.ascent));
cStyle.left = Math.round(size.convert(minX));

wStyle.height = size.convert(font.height) + 'px';

var color = style.get('color');
var chars = Cufon.CSS.textTransform(text, style).split('');

var jumps = font.spacing(chars,
getSpacingValue(el, style, size, 'letterSpacing'),
getSpacingValue(el, style, size, 'wordSpacing')
);

if (!jumps.length) return null;

var width = jumps.total;
var fullWidth = -minX + width + (viewBox.width - jumps[jumps.length - 1]);

var shapeWidth = size.convert(fullWidth * stretchFactor), roundedShapeWidth = Math.round(shapeWidth);

var coordSize = fullWidth + ',' + viewBox.height, coordOrigin;
var stretch = 'r' + coordSize + 'ns';

var fill = options.textGradient && gradientFill(options.textGradient);

var glyphs = font.glyphs, offsetX = 0;
var shadows = options.textShadow;
var i = -1, j = 0, chr;

while (chr = chars[++i]) {

var glyph = glyphs[chars] || font.missingGlyph, shape;
if (!glyph) continue;

if (redraw) {
// some glyphs may be missing so we can't use i
shape = canvas.childNodes[j];
while (shape.firstChild) shape.removeChild(shape.firstChild); // shadow, fill
}
else {
shape = document.createElement('cvml:shape');
canvas.appendChild(shape);
}

shape.stroked = 'f';
shape.coordsize = coordSize;
shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY;
shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + coordOrigin + stretch;
shape.fillcolor = color;

if (fill) shape.appendChild(fill.cloneNode(false));

// it's important to not set top/left or IE8 will grind to a halt
var sStyle = shape.style;
sStyle.width = roundedShapeWidth;
sStyle.height = roundedHeight;

if (shadows) {
// due to the limitations of the VML shadow element there
// can only be two visible shadows. opacity is shared
// for all shadows.
var shadow1 = shadows[0], shadow2 = shadows[1];
var color1 = Cufon.CSS.color(shadow1.color), color2;
var shadow = document.createElement('cvml:shadow');
shadow.on = 't';
shadow.color = color1.color;
shadow.offset = shadow1.offX + ',' + shadow1.offY;
if (shadow2) {
color2 = Cufon.CSS.color(shadow2.color);
shadow.type = 'double';
shadow.color2 = color2.color;
shadow.offset2 = shadow2.offX + ',' + shadow2.offY;
}
shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1;
shape.appendChild(shadow);
}

offsetX += jumps[j++];
}

// addresses flickering issues on :hover

var cover = shape.nextSibling, coverFill, vStyle;

if (options.forceHitArea) {

if (!cover) {
cover = document.createElement('cvml:rect');
cover.stroked = 'f';
cover.className = 'cufon-vml-cover';
coverFill = document.createElement('cvml:fill');
coverFill.opacity = 0;
cover.appendChild(coverFill);
canvas.appendChild(cover);
}

vStyle = cover.style;

vStyle.width = roundedShapeWidth;
vStyle.height = roundedHeight;

}
else if (cover) canvas.removeChild(cover);

wStyle.width = Math.max(Math.ceil(size.convert(width * stretchFactor)), 0);

if (HAS_BROKEN_LINEHEIGHT) {

var yAdjust = style.computedYAdjust;

if (yAdjust === undefined) {
var lineHeight = style.get('lineHeight');
if (lineHeight == 'normal') lineHeight = '1em';
else if (!isNaN(lineHeight)) lineHeight += 'em'; // no unit
style.computedYAdjust = yAdjust = 0.5 * (getSizeInPixels(el, lineHeight) - parseFloat(wStyle.height));
}

if (yAdjust) {
wStyle.marginTop = Math.ceil(yAdjust) + 'px';
wStyle.marginBottom = yAdjust + 'px';
}

}

return wrapper;

};

})());

Cufon.registerEngine('canvas', (function() {

// Safari 2 doesn't support .apply() on native methods

var check = document.createElement('canvas');
if (!check || !check.getContext || !check.getContext.apply) return;
check = null;

var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block');

// Firefox 2 w/ non-strict doctype (almost standards mode)
var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (document.compatMode == 'BackCompat' || /frameset|transitional/i.test(document.doctype.publicId));

var styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.appendChild(document.createTextNode((
'cufon{text-indent:0;}' +
'@media screen,projection{' +
'cufon{display:inline;display:inline-block;position:relative;vertical-align:middle;' +
(HAS_BROKEN_LINEHEIGHT
? ''
: 'font-size:1px;line-height:1px;') +
'}cufon cufontext{display:-moz-inline-box;display:inline-block;width:0;height:0;text-align:left;text-indent:-10000in;}' +
(HAS_INLINE_BLOCK
? 'cufon canvas{position:relative;}'
: 'cufon canvas{position:absolute;}') +
'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy{display:none;}' +
'cufonglue{white-space:nowrap;display:inline-block;}' +
'.cufon-viewport-resizing cufonglue{white-space:normal;}' +
'}' +
'@media print{' +
'cufon{padding:0;}' + // Firefox 2
'cufon canvas{display:none;}' +
'}'
).replace(/;/g, '!important;')));
document.getElementsByTagName('head')[0].appendChild(styleSheet);

function generateFromVML(path, context) {
var atX = 0, atY = 0;
var code = [], re = /([mrvxe])([^a-z]*)/g, match;
generate: for (var i = 0; match = re.exec(path); ++i) {
var c = match[2].split(',');
switch (match[1]) {
case 'v':
code = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] };
break;
case 'r':
code = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] };
break;
case 'm':
code = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] };
break;
case 'x':
code = { m: 'closePath' };
break;
case 'e':
break generate;
}
context[code.m].apply(context, code.a);
}
return code;
}

function interpret(code, context) {
for (var i = 0, l = code.length; i < l; ++i) {
var line = code;
context[line.m].apply(context, line.a);
}
}

return function(font, text, style, options, node, el) {

var redraw = (text === null);

if (redraw) text = node.getAttribute('alt');

var viewBox = font.viewBox;

var size = style.getSize('fontSize', font.baseSize);

var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0;
var shadows = options.textShadow, shadowOffsets = [];
if (shadows) {
for (var i = shadows.length; i--;) {
var shadow = shadows;
var x = size.convertFrom(parseFloat(shadow.offX));
var y = size.convertFrom(parseFloat(shadow.offY));
shadowOffsets = [ x, y ];
if (y < expandTop) expandTop = y;
if (x > expandRight) expandRight = x;
if (y > expandBottom) expandBottom = y;
if (x < expandLeft) expandLeft = x;
}
}

var chars = Cufon.CSS.textTransform(text, style).split('');

var jumps = font.spacing(chars,
~~size.convertFrom(parseFloat(style.get('letterSpacing')) || 0),
~~size.convertFrom(parseFloat(style.get('wordSpacing')) || 0)
);

if (!jumps.length) return null; // there's nothing to render

var width = jumps.total;

expandRight += viewBox.width - jumps[jumps.length - 1];
expandLeft += viewBox.minX;

var wrapper, canvas;

if (redraw) {
wrapper = node;
canvas = node.firstChild;
}
else {
wrapper = document.createElement('cufon');
wrapper.className = 'cufon cufon-canvas';
wrapper.setAttribute('alt', text);

canvas = document.createElement('canvas');
wrapper.appendChild(canvas);

if (options.printable) {
var print = document.createElement('cufontext');
print.appendChild(document.createTextNode(text));
wrapper.appendChild(print);
}
}

var wStyle = wrapper.style;
var cStyle = canvas.style;

var height = size.convert(viewBox.height);
var roundedHeight = Math.ceil(height);
var roundingFactor = roundedHeight / height;
var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
var stretchedWidth = width * stretchFactor;

var canvasWidth = Math.ceil(size.convert(stretchedWidth + expandRight - expandLeft));
var canvasHeight = Math.ceil(size.convert(viewBox.height - expandTop + expandBottom));

canvas.width = canvasWidth;
canvas.height = canvasHeight;

// needed for WebKit and full page zoom
cStyle.width = canvasWidth + 'px';
cStyle.height = canvasHeight + 'px';

// minY has no part in canvas.height
expandTop += viewBox.minY;

cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px';
cStyle.left = Math.round(size.convert(expandLeft)) + 'px';

var wrapperWidth = Math.max(Math.ceil(size.convert(stretchedWidth)), 0) + 'px';

if (HAS_INLINE_BLOCK) {
wStyle.width = wrapperWidth;
wStyle.height = size.convert(font.height) + 'px';
}
else {
wStyle.paddingLeft = wrapperWidth;
wStyle.paddingBottom = (size.convert(font.height) - 1) + 'px';
}

var g = canvas.getContext('2d'), scale = height / viewBox.height;

// proper horizontal scaling is performed later
g.scale(scale, scale * roundingFactor);
g.translate(-expandLeft, -expandTop);
g.save();

function renderText() {
var glyphs = font.glyphs, glyph, i = -1, j = -1, chr;
g.scale(stretchFactor, 1);
while (chr = chars[++i]) {
var glyph = glyphs[chars] || font.missingGlyph;
if (!glyph) continue;
if (glyph.d) {
g.beginPath();
if (glyph.code) interpret(glyph.code, g);
else glyph.code = generateFromVML('m' + glyph.d, g);
g.fill();
}
g.translate(jumps[++j], 0);
}
g.restore();
}

if (shadows) {
for (var i = shadows.length; i--;) {
var shadow = shadows;
g.save();
g.fillStyle = shadow.color;
g.translate.apply(g, shadowOffsets);
renderText();
}
}

var gradient = options.textGradient;
if (gradient) {
var stops = gradient.stops, fill = g.createLinearGradient(0, viewBox.minY, 0, viewBox.maxY);
for (var i = 0, l = stops.length; i < l; ++i) {
fill.addColorStop.apply(fill, stops);
}
g.fillStyle = fill;
}
else g.fillStyle = style.get('color');

renderText();

return wrapper;

};

})());


I hope that helps anyone with the IE9 issue.
 
Status
Not open for further replies.

The Rule #1

Do not insult any other member. Be polite and do business. Thank you!

Members online

Featured Services

Sedo - it.com Premiums

IT.com

Premium Members

AucDom
UKBackorder
Be a Squirrel
Acorn Domains Merch
MariaBuy Marketplace

New Threads

Domain Forum Friends

Other domain-related communities we can recommend.

Our Mods' Businesses

Perfect
Service
Laskos
*the exceptional businesses of our esteemed moderators
Top Bottom