Domain Manage

IE9 Cufon / Prettyphoto Problem

Discussion in 'Website Design' started by Aegean, Apr 18, 2011.

Thread Status:
Not open for further replies.
  1. Aegean

    Aegean Active Member

    Joined:
    Feb 2011
    Posts:
    752
    Likes Received:
    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[i];
    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[i];
    var x = size.convertFrom(parseFloat(shadow.offX));
    var y = size.convertFrom(parseFloat(shadow.offY));
    shadowOffsets[i] = [ 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[i]] || 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[i];
    g.save();
    g.fillStyle = shadow.color;
    g.translate.apply(g, shadowOffsets[i]);
    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[i]);
    }
    g.fillStyle = fill;
    }
    else g.fillStyle = style.get('color');

    renderText();

    return wrapper;

    };

    })());


    I hope that helps anyone with the IE9 issue.[/i][/i][/i][/i][/i][/i][/i]
     
  2. Domain Forum

    Acorn Domains Elite Member

    Joined:
    1999
    Messages:
    Many
    Likes Received:
    Lots
     
Thread Status:
Not open for further replies.

Share This Page