Monday, April 21, 2014

Bootstrap 3 HTML Template with CDN Failover for JS and CSS

I wanted to create a nice, simple template for Bootstrap 3.0 that uses a failover technique I learned about at a recent ASP.NET user group meeting (Thanks Alek Davis).

The Getting Started section of http://getbootstrap.com shows a CDN example, but the HTML template that assumes you have local Bootstrap JS and CSS files.  I found lots of examples of Javascript failover techniques, most notably Scott Hanselman’s CDNs fail, but your scripts don’t have to… blog post. A little more Googling turned up this technique to see if Bootstrap loaded properly. I adapted the code from github to the shorthand code from Scott’s blog to create this nice Bootstrap 3 HTML template that attempts to load JQuery and the Bootstrap 3 JS and CSS files from CDN. Should any fail, it loads the files locally.

Note: This template is expecting the following local resources:
js/jquery-1.11.0.min.js
js/bootstrap.min.js
css/bootstrap.min.css

May not be IE compatible!

 <!DOCTYPE html>  
 <html lang="en">  
  <head>  
   <meta charset="utf-8">  
   <meta http-equiv="X-UA-Compatible" content="IE=edge">  
   <meta name="viewport" content="width=device-width, initial-scale=1">  
   <title>Bootstrap 101 Template</title>  
   <!-- Latest compiled and minified Bootstrap 3 CSS CDN-->  
   <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">  
  </head>  
  <body>  
   <h1>Hello, world!</h1>  
   <!-- jQuery (necessary for Bootstrap's JavaScript plugins) CDN Failover -->  
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>  
   <script>window.jQuery || document.write('<script src="js/jquery-1.11.0.min.js">\x3C/script>');</script>   
   <!-- Include all compiled plugins (below), or include individual files as needed -->  
   <!-- Latest compiled and minified JavaScript CDN Failover-->  
   <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>  
   <script>$.fn.modal || document.write('<script src="js/bootstrap.min.js">\x3C/script>');</script>  
   <script>  
   $(document).ready(function() {  
     //CSS CDN Failover (If you change the body color, you will need to change the rgb value below.)  
     $('body').css("color") == 'rgb(51, 51, 51)' || $("head").prepend("<link rel='stylesheet' href='css/bootstrap.min.css' type='text/css' media='screen'>");  
   });  
   </script>  
  </body>  
 </html>  

References:
Scott Hanselman: CDNs fail, but your scripts don't have to - fallback from CDN to local jQuery
GitHub MaxCDN / bootstrap-cdn: Check if Bootstrap is loaded #111
Bootstrap Website: http://getbootstrap.com

Thursday, April 10, 2014

ColdFusion 10 CFLOOP bug with decimal steps

Back in the ColdFusion MX 6.1 era, I stumbled across a bug. A CFLOOP tag with a step of 0.2 would inexplicably skip a number (32.0, I believe) as it counted up. The bug persisted through version 7.x. I had a workaround in place, so I didn’t give it much thought after that.

Recent ColdFusion conversations made me think of this bug, so I decided to code up a quick test to see if it was still an issue with CF10. What I discovered was far worse than I remembered.

Start with a simple loop from 0 to 40 with a step of 0.2. Display each step and add a comma after all but the last number:
<cfloop index="i" from="0" to="40" step="0.2">
      <cfoutput>#i#</cfoutput>
      <cfif i LT 40>, </cfif>
</cfloop>

Hmmm… 40 is missing. When counting up by integers, 40 is included. This was the first hint that something was not quite right.


The list is a bit tough to read, so let’s break it up by inserting a <BR> before each integer (skipping the initial zero).

<cfloop index="i" from="0" to="40" step="0.2">
      <cfif int(i) EQ i and i GT 0><BR></cfif>
      <cfoutput>#i#</cfoutput>
      <cfif i LT 40>, </cfif>
</cfloop>

This should have produced a nice column of integers with each row ending in x.8! 

There is a line break after 0.8, as expected, but no line breaks again until 8.8 and no more again until 37.8? This makes no sense. Since the problem occurs in the first 10 digits, let’s reduce the TO value to 10 and include “int(i)” and the result of the evaluation “int(i) eq i” in the output:
<cfloop index="i" from="0" to="10" step="0.2">
      <cfif int(i) EQ i and i GT 0><BR></cfif>
      <cfoutput>#int(i)# EQ #i#:#int(i) EQ i#</cfoutput>
      <cfif i LT 10>, </cfif>
</cfloop>


So, this output is telling me that when i = 2 , int(i) EQ i evaluatees to 1 EQ 2! Worse, it is saying 4 <> 4, 5 <> 5, 6 <> 6 but 7 = 7? I tried the other rounding functions: FIX, ROUND and CEILING with varying degrees of weirdness. (ROUND appeared to work, but I don’t trust it completely.) I also tried JavaCast() but the results were still off. The string comparison function COMPARE (x,y) had the same problem. When I tried int(2.0) by itself, it did not yield “1”, so I suspect the problem is data type conversion in the processing of the loop steps.

The Workaround
I used the same workaround here that I used years ago with the original problem. Multiply the FROM, TO and STEP by 10 and divide the value as appropriate inside the loop.
<cfloop index="i" from="0" to="100" step="2">
      <cfif i MOD 10 EQ 0 and i GT 0><BR></cfif>
      <cfoutput>#numberformat(i/10,"09.9")#</cfoutput>
      <cfif i LT 100>, </cfif>
</cfloop>

And the results turn out as expected:

Conclusion
Avoid decimal steps.