Solved: Cufon text not refreshing on jQuery UI Tabs

Update: I no longer use Cufon in my projects and prefer @font-face. If you are struggling with Cufon it will actually be faster for you to replace it with @font-face than to figure out your Cufon problems. Start with this tutorial here: The Essential Guide to @font-face

Today I was working on a project that:

  1. Made use of jQuery UI Tabs through the WordPress Post Tabs plugin
  2. Uses custom fonts for the tabs via Cufon
  3. Requires tab font to change color when selected

My first attempt was to simply render the tabs with Cufon…

jQuery(document).ready(function($){
    Cufon.replace('.ui-tabs .ui-tabs-nav li a');
});

..and style the active and default states with CSS.

/* default tab style */
.ui-tabs .ui-tabs-nav li a {
    color: #454545;
}

/* selected tab style */
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
    color: #FFFFFF;
}

So far so good. The tabs were customized quite heavily and now looked like this.

However, there was a problem: the Cufon text wasn’t changing color when you clicked on different tabs.

The reason for this is because Cufon has already rendered on the page, and because there is no page reload when you click the tabs, Cufon doesn’t re-render to update the fonts and colors.

Checking the Cufon documentation, I found that you could manually refresh Cufon by calling the Cufon.refresh() function. With jQuery UI Tabs you can bind the refresh function to fire after the tabsshow event:

$('#tabs_0').bind('tabsshow', function() {
    Cufon.refresh('.ui-tabs .ui-tabs-nav li a');
});

Now the tab fonts and colors update when you click on the tabs, yay!

One more thing. In the code above I had to target the #tabs_0 selector because that is the selector which the Post Tabs plugin uses to render the tabs. However this wasn’t very flexible because it wouldn’t match the other instances of the jQuery UI Tabs which would have the IDs of #tabs_1, #tabs_2, #tabs_3.. #tabs_n.

So I turned to Twitter and within minutes I had my answer (thanks @cheeaun!). Simply use jQuery’s Attribute Starts With Selector:

$('[id^="tabs_"]').bind('tabsshow', function() {
    Cufon.refresh('.ui-tabs .ui-tabs-nav li a');
});

Now, the Tabs are a lot more bulletproof.

  1. Cufon text will be updated when new tabs are selected
  2. The code applies to multiple tabs generated by the Post Tabs plugin, i.e. #tabs_1, #tabs_2, #tabs_3.. #tabs__n_.

I hope this saves a few people the time spent figuring this out.

25 Comments on "Solved: Cufon text not refreshing on jQuery UI Tabs"

  • pelf says

    Parlez vous anglais?

    • blogjunkie says

      I’m not speaking French (or Greek), just Geek – web development dialect

  • Jonathan says

    Hello,

    you can ehlp me please.

    i have a magento store i like implement the cufon replace for a regular price, this prices if the product have a opcions increase the price.

    im follow your tips but are imposible chambge.

    Please take a look.

    This its my code.


    <!-- All this contain a Replace -->
    __('Regular Price:') ?> <!-- this its the title -->
    <span class="price-cu " id="old-price-getIdSuffix() ?>"> <!-- this its the class need replace / this in the first price its done (cufon replace) whe the price incremente no more replace -->
    currency($_regularPrice,true,false) ?> <!-- Save for Web Slices (precios.psd) -->

    in advance if you have a tip ty…

    • blogjunkie says

      Hi Jonathan, since I don’t have your JS code I can only guess. Assuming that it’s the same DOM element that is changing (i.e. you are not hiding and displaying something else), your jQuery code should be something like:

      $('.price-cu').priceChange(function() {
      Cufon.refresh('.price-cu');
      });

  • Job says

    Thanks for this post. You saved my day.

    • blogjunkie says

      Awesome! My work is done

  • rick says

    How can I bind cufon refresh to:

    $(document).ready(function() {
    	//When page loads...
    	$(".tab_content").hide(); //Hide all content
    	$("ul.tabs li:first").addClass("active").show(); //Activate first tab
    	$(".tab_content:first").show(); //Show first tab content
    
    	//On Click Event
    	$("ul.tabs li").click(function() {
    
    		$("ul.tabs li").removeClass("active"); //Remove any "active" class
    		$(this).addClass("active"); //Add "active" class to selected tab
    		$(".tab_content").hide(); //Hide all tab content
    
    		var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab   content
    		$(activeTab).fadeIn(); //Fade in the active ID content
    		return false;
    	});
    });
    

    any suggestions? I have barely found anything dealing with this and you seem to be the expert. any help is appreciated!

  • blogjunkie says

    Hi Rick, I’m not an expert but I can try to help! I think you need to call the Cufon.refresh() function after the tab content has been faded in. Try:

    $(activeTab).fadeIn( function() {
    	Cufon.refresh('.tab_content');
    });
    
    • Wow, you’re the man! Thank you. From now on, i will charge more for Cufon implementation.

      • blogjunkie says

        Actually I’m starting to use @font-face more and more for custom fonts. It’s not very difficult too! Just use the Font Squirrel generator and follow the examples from the generated files – http://www.fontsquirrel.com/fontface/generator

  • rick says

    that was pretty close. With cufon you have to declare all the elements that have are using Cufon for the refresh to work.

    Thanks for the help and documenting this issue.

    • blogjunkie says

      That’s awesome! Glad I could help

  • so, not to be lazy or needy… but I’m tired and really need your help…

    have a peek at http://thetoystreet.com/index_black.html and help me with my cufon issues!

    • blogjunkie says

      Hi Sean, does your script have a callback function? You need to call Cufon.refresh() from within the callback function. Sorry I can’t be more specific than that. Good luck!

    • rick says

      Sean,

      Your link is not working.

      In your function you need something like: Cufon.refresh(‘h3, h2, h4′); – from what I read you must refresh all the cufon instances on the page.

      Hope this helps.

  • alvaro says

    Hi dude maybe u can helpe me..

     <ul class="abas2 tabs">
                    <li><a href="#carros-destaque" ><span>VE&Iacute;CULOS EM</span>Destaque</a></li>
                    <li><a href="#carros-ofertas" ><span>GRANDES</span>Ofertas</a></li>
                    <li><a href="#carros-acessados" ><span>VE&Iacute;CULOS MAIS</span>Acessados</a></li>
    	        </ul>
    
    Cufon.replace('#listaDestaque ul.tabs li a.current', { fontFamily: 'Myriad Pro Bold Italic', color: '-linear-gradient(0.3=#FFB300, 1=#FF6600)' });
    Cufon.replace('#listaDestaque ul.tabs li a', { fontFamily: 'Myriad Pro Semibold Italic', color: '-linear-gradient(0.4=#FFFFFF, 1=#00CCFF)' });
    
    Cufon.replace('#listaDestaque ul.tabs li a.current span', { fontFamily: 'Redensek', color: '-linear-gradient(0=#155595, 1=#082038)' });
    Cufon.replace('#listaDestaque ul.tabs li a span', { fontFamily: 'Redensek', color: '-linear-gradient(0=#FFFF00, 1=#FF9900)' });
    
    
    

    i m usign http://flowplayer.org/tools/demos/tabs/

    jQuery(“ul.tabs”).tabs(“div.panes > div”);

    i can put cufon work on inactive tabs but when the tab coming active (class=”current”) the Cufon Font dont change

    • blogjunkie says

      Hi Alvaro, from the flowplayer website I see that there is documentation on API & Events. Based on this and the example on this page, I’m guessing that you will need to use this code:

      // first initialize the tabs
      $(".tabs").tabs(".panes > div");
      
      // get handle to the api (must have been constructed before this call)
      var api = $("ul.tabs").data("tabs");
      
      // Refresh Cufon each time a tab is clicked
      api.onClick(function(e, index) {
      	Cufon.replace('#listaDestaque ul.tabs li a.current span', { fontFamily: 'Redensek', color: '-linear-gradient(0=#155595, 1=#082038)' });
      	Cufon.replace('#listaDestaque ul.tabs li a span', { fontFamily: 'Redensek', color: '-linear-gradient(0=#FFFF00, 1=#FF9900)' });
      });
      

      Test and adjust this yourself – like I said, I’m mainly guessing since I don’t have time to create a test. Otherwise, try to embed your fonts using @font-face – it’s much easier and more bulletproof!

      http://www.fontsquirrel.com/fontface/generator

  • Daniele says

    hello,
    I can not do this script …
    where it is inserted in the code?
    in the body or head?

    thanks

    Daniel

    • David says

      Hi Daniele, you place the code wherever you are initiating cufon or jQuery.

      • Daniele says

        I insert this code in the head

        Cufon.replace(‘.ui-tabs .ui-tabs-nav li a’, { fontFamily: ‘Kozuka Gothic Pro OpenType’, hover:true});

        $(‘[id^=”tabs_”]’).bind(‘tabsshow’, function() {
        Cufon.refresh(‘.ui-tabs .ui-tabs-nav li a’);
        });

        , but i
        can not do this script..

        Where i am wrong?

        Thanks

  • Luciano says

    Hi dude! maybe you could help me.
    I´m trying to implement cufon in a site with a jquery count up.
    Everything works fine except for the counte itself.
    As far as I figured, the problem is that cufon should refresh after the page is loaded but I can´t make it work.

    The code I´m using is this:
    jQuery(function($) {
    $(‘.timer’).countTo({
    });
    });

    And there´s another .js file wich is called before:

    (function($) {
    $.fn.countTo = function(options) {
    // merge the default plugin settings with the custom options
    options = $.extend({}, $.fn.countTo.defaults, options || {});

    // how many times to update the value, and how much to increment the value on each update
    var loops = Math.ceil(options.speed / options.refreshInterval),
    increment = (options.to – options.from) / loops;

    return $(this).each(function() {
    var _this = this,
    loopCount = 0,
    value = options.from,
    interval = setInterval(updateTimer, options.refreshInterval);

    function updateTimer() {
    value += increment;
    loopCount++;
    //$(_this).html(value.toFixed(options.decimals));
    //$(_this).html(addCommas(value.toFixed(options.decimals)))
    $(_this).html(addSeparatorsNF(value.toFixed(options.decimals), ‘.’, ‘,’, ‘.’))
    // addSeparatorsNF(‘52093423.003′, ‘.’, ‘,’, ‘.’)
    // 52.093.423,003

    if (typeof(options.onUpdate) == ‘function’) {
    options.onUpdate.call(_this, value);
    }

    if (loopCount >= loops) {
    clearInterval(interval);
    value = options.to;

    if (typeof(options.onComplete) == ‘function’) {
    options.onComplete.call(_this, value);
    }
    }
    }

    function addSeparatorsNF(nStr, inD, outD, sep)
    {
    nStr += ”;
    var dpos = nStr.indexOf(inD);
    var nStrEnd = ”;
    if (dpos != -1) {
    nStrEnd = outD + nStr.substring(dpos + 1, nStr.length);
    nStr = nStr.substring(0, dpos);
    }
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(nStr)) {
    nStr = nStr.replace(rgx, ‘$1′ + sep + ‘$2′);
    }
    return nStr + nStrEnd;
    }
    });
    };

    $.fn.countTo.defaults = {
    from: 0, // the number the element should start at
    to: 100, // the number the element should end at
    speed: 8, // how long it should take to count between the target numbers
    refreshInterval: 50, // how often the element should be updated
    decimals: 1, // the number of decimal places to show
    onUpdate: null, // callback method for every time the element is updated,
    onComplete: null, // callback method for when the element finishes updating
    };

    })(jQuery);

    Any idea?
    Thanks in advance and sorry for my poor english!

    Luciano

  • Imre says

    Hello,

    Can you please me, having some issues with Cufon.

    I’m using Cufon for a custom font on a site I’m working on. I applayed the Cufon font on the top links. So far everything is OK.

    Here is my issue: As I’m making a responsive site, I want the font to change from the custom Cufon to a regular one, after the window is resized to a screen size less than 767px wide.

    For this I am using the removeClass event:

    if ( $(window).width() < 767) {
    $('li').removeClass('newFont');
    }

    The issue is that the Cufon font won’t get replaced until the page is refreshed.

    I tried with the Cufon.refresh() event like this:

    if ( $(window).width() < 767) {
    $('li').removeClass('newFont');
    Cufon.refresh();
    }

    But that doesn’t work either, the font doesn’t get replaced until I manually refresh the page.

    Any help would be much appreciated.

    Thank you in advance.

    • Imre says

      Wanted to say: Can you please HELP me, having some issues with Cufon.

  • Hi Imre

    if ( $(window).width() < 767) won't work because it only performs the check when the page loads, and not when you change the viewport width. If you need to trigger javascript when you enter a new breakpoint here are some options

    http://stackoverflow.com/questions/11387391/how-to-call-different-jquery-actions-in-responsive-design

    http://xoxco.com/projects/code/breakpoints/

    Of course, you would avoid this problem completely if you use @font-face. It's certainly not as difficult as figuring Cufon out!

  • Imre says

    Hi David,

    Thank you for the fast respond.

    @font-face was my first attempt, but the font I wanted to use did not render nicely (rendered very bad) in Chrome and Opera, so that is the reason why I wanted to go with Cufon.

    But I gave up on Cufon, I better go with some other font (even if I take a bit out from the design). Cufon is really a pain to use…

    Thank you again for your tips.

    Imre