{"id":2690,"date":"2012-12-26T15:18:39","date_gmt":"2012-12-26T21:18:39","guid":{"rendered":"http:\/\/bililite.com\/blog\/?p=2690"},"modified":"2013-01-03T10:18:14","modified_gmt":"2013-01-03T16:18:14","slug":"themeswitcher-is-dead-long-live-themeswitcher","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2012\/12\/26\/themeswitcher-is-dead-long-live-themeswitcher\/","title":{"rendered":"<code>themeswitcher<\/code> is dead. Long live <code>themeswitcher<\/code>"},"content":{"rendered":"<p>The <a href=\"\/bililite\">bilirubin graph<\/a> uses jQuery UI and used to use the official theme switching widget, which I just discovered <a href=\"http:\/\/bugs.jqueryui.com\/ticket\/8149\">has been broken since September 2012<\/a>. That's the problem with graceful degradation; when something breaks the page still works so smoothly I don't notice unless I'm paying close attention. Anyway, David Hoff has written a replacement, <a href=\"https:\/\/github.com\/harborhoffer\/Super-Theme-Switcher\">Super Theme Switcher<\/a> which works well, but requires an explicit option to tell the plugin where to find the sample images:<p>\r\n<pre><code class=\"language-javascript\" >$('#themeswitcher').themeswitcher({\r\n\timgpath: '\/inc\/themeswitcher\/images\/'\r\n});<\/code><\/pre>\r\n<p>The other thing I needed was a way to detect the change in theme. <code>themeswitcher<\/code> has an <code>onSelect<\/code> callback, but that is called when the new stylesheet is added to the page, not when it is actually loaded. I previously used <a href=\"\/blog\/2009\/06\/24\/copying-jquery-ui-styles-and-detecting-css-loading\/\" title=\"Copying jQuery UI styles and Detecting CSS Loading\">a hack with fake images<\/a>. But that was a terrible hack. Chrome still doesn't trigger <code>load<\/code> events for stylesheets, so that won't work. But all the modern browsers support <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/CSS\/Tutorials\/Using_CSS_transitions\">CSS transitions<\/a>, including the <code>transitionend<\/code> event (webkit requires a prefix).<\/p>\r\n<p>So to detect a change in stylesheet that affects, say, elements with a class of <code>ui-state-default<\/code>, do the following:<\/p>\r\n<pre><code class=\"language-javascript\" >var div = $('&lt;div class=ui-state-default&gt;').css({\r\n  transition: 'color 0.01s',\r\n  webkitTransition: 'color 0.01s',\r\n  visibility: 'hidden' \/\/ make sure the element is invisible\r\n}).appendTo('body').on('transitionend webkitTransitionEnd', function(){\r\n  alert $(this).css('color'); \/\/ or whatever\r\n});<\/code><\/pre>\r\n<p>Internet Explorer, of course, doesn't support CSS transitions (we'll see about IE 10), but luckily they are the only ones to correctly support stylesheet <code>load<\/code> events and we can use <code class=\"language-javascript\" >$('link:last').one('load', function(){ whatever });<\/code>. So we can detect stylesheet loading in either case, and create a new version of <code>themeswitcher<\/code> that calls the <code>onSelect<\/code> callback when the stylesheet is loaded, not when it is added:<\/p>\r\n<pre><code class=\"language-javascript\" >\/\/ create the test div\r\nvar div = $('&lt;div class=ui-state-default&gt;').css({\r\n\ttransition: 'color 0.01s',\r\n\twebkitTransition: 'color 0.01s',\r\n\tvisibility: 'hidden'\r\n}).appendTo('body');\r\n\r\n \/\/ decide if we can handle CSS transitions\r\n$.support.transition =\r\n document.body.style.transition !== undefined ||\r\n document.body.style.webkitTransition !== undefined;\r\n\r\n$.fn.themeswitcher2 = function(opts){\r\n\tif (opts.onSelect && $.support.transition){\r\n\t\tdiv.on('transitionend webkitTransitionEnd', opts.onSelect);\r\n\t\tdelete opts.onSelect;\r\n\t}else if (opts.onSelect){\r\n\t\t\/\/ this is really browser sniffing; it turns out that the only major browser that doesn't support transitions is IE, and they support\r\n\t\t\/\/ the stylesheet onload event\r\n\t\t\/\/ We know that themeswitcher adds the last stylesheet, so tie into that load event\r\n\t\tvar onSelect = opts.onSelect;\r\n\t\topts.onSelect = function(){\r\n\t\t\t$('link:last').one('load', onSelect);\r\n\t\t};\r\n\t}\r\n\treturn this.themeswitcher(opts);\r\n};<\/code><\/pre>\r\n<p>And this works in Chrome, Firefox, Opera and IE. See it in action on the <a href=\"http:\/\/bililite.com\/bililite\/\">bilirubin graph<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"The bilirubin graph uses jQuery UI and used to use the official theme switching widget, which I just discovered has been broken since September 2012. That's the problem with graceful degradation; when something breaks the page still works so smoothly I don't notice unless I'm paying close attention. Anyway, David Hoff has written a replacement, [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,5],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2690"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=2690"}],"version-history":[{"count":17,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2690\/revisions"}],"predecessor-version":[{"id":2715,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2690\/revisions\/2715"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=2690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=2690"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=2690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}