<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    <channel>
        <title>JavaScript - Blogs at Near Infinity</title>


        <link>http://www.nearinfinity.com/blogs/</link>
        <description>Employee Blogs</description>
        <language>en</language>
        <copyright>Copyright 2012</copyright>
        <lastBuildDate>Tue, 23 Aug 2011 23:09:48 -0500</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>Integrating JavaScript and C# with Script#</title>
            <description><![CDATA[<p>Have you ever had an enum in your server code that you wanted to access in client side code?  Or wanted the safety of compile time errors when there are discrepancies between your server-side and client-side code?  Or had a C# Data Transfer Object (DTO) that you wanted to enable Intellisense for in JavaScript?  I hadn't found a good solution either ... until now.</p>
<p><b>Compiling C# to What!?</b></p>

<div style="float:right; overflow: auto; margin-left:10px;">
<script type='text/javascript'> 
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2011/08/integrating-javascript-and-c-with.html';
 
        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
 
        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);
 
        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);
 
        document.write(div.innerHTML);
    </script> 
</div>

<p>Compiling C# code into JavaScript may seem foreign, but <a href=" http://projects.nikhilk.net/ScriptSharp ">Script#</a> is a mature technology that is absolutely worth a look.  Our team has been using it very happily for about three months.  We've found a number of benefits  including:</p>

<ul>
<li>Consistently working Intellisense</li>
<li>Better encapsulation</li>
<li>Simpler Object Orientation</li>
<li>Easier deployment (Script# compiles multiple files to a single, optionally minified file)</li>
<li>Safer refactoring</li>
<li>Simpler unit testing</li>
<li>Type safety; and</li>
<li>Design time syntax checking (no more mistyping a variable and accidentally declaring it to the global scope)</li>
</ul>

<p>Scott Hanselman covered most of these topics in last month's Hanselminutes episode: <a href=" http://www.hanselminutes.com/default.aspx?showID=296">Script# Compiles to JavaScript</a>.  If you have a spare car ride I definitely recommend the listen.  But what wasn't covered were some additional benefits provided by an off the beaten path approach to this great technology.  The main benefit is tighter server side C# to client side JavaScript integration.  A secondary benefit is less of a dependency on Script#.</p>

<p><b>To the Command Line</b></p>

<p>Typically to get going with Script# you: </p>

<ol>
<li>Install the Script# Visual Studio plug-in</li>
<li>File -> New project</li>
<li>Select "Script Library" and</li>
<li>Compile to generate JavaScript</li>
</ol>

<p>Nice and easy.  The down side to this approach is you can't easily include files outside of your project.  Specifically, you can't include data transfer objects or enum's from your server side code.  Furthermore, all of your team members must install Script#.  If instead you compile with Script#'s "ssc.exe" command you obtain more control and get less dependency.</p>

<p><b>How-To</b></p>

<p>The how-to looks something like this:</p>

<ol>

<li><a href="http://projects.nikhilk.net/ScriptSharp">Download</a> and install Script#</li>
<li>Add a Class Library (not a Script# project)</li>
<li>Project properties -> Build -> Advanced -> "Do not reference mscorlib"<br />
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-u7QvzHOOfxE/TlRhVwoGyII/AAAAAAAABu8/Vonkzc8nNLc/s1600/mscorlib.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 235px;" src="http://4.bp.blogspot.com/-u7QvzHOOfxE/TlRhVwoGyII/AAAAAAAABu8/Vonkzc8nNLc/s400/mscorlib.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5644243259460339842" /></a>
</li>

<li>Ideally move the Script# files (C:\Program Files (x86)\ScriptSharp) locally to the solution and check them into source control to a Libs or something similar</li>

<li>Remove all references, but add: ScriptSharp.dll, ScriptSharp.Web.dll, Script.Jquery</li>
<li>Edit your .csproj to manually reference Script#'s mscorlib (right click, Unload project, Edit MyProject.csproj)<br />
    <br />
    <span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">&lt;</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:#A31515;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">Reference</span><span style="font-size:9.5pt;
line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA"> </span>
    <span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;color:red;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">Include</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;color:blue;mso-ansi-language:EN-US;
mso-fareast-language:EN-US;mso-bidi-language:AR-SA">=</span><span style="font-size:9.5pt;line-height:115%;font-family:Consolas;mso-fareast-font-family:
Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA">&quot;<span style="color:blue">mscorlib, Version=0.7.0.0, 
    Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4, processorArchitecture=MSIL</span>&quot;<span 
        style="color:blue">&gt;<br />
    <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="color:#A31515">SpecificVersion</span><span 
        style="color:blue">&gt;</span>True<span style="color:blue">&lt;/</span><span 
        style="color:#A31515">SpecificVersion</span><span style="color:blue">&gt;<br />
    <span style="mso-spacerun:yes">&nbsp; </span>&lt;</span><span style="color:#A31515">HintPath</span><span 
        style="color:blue">&gt;</span>..\Libs\ScriptSharp\v1.0\mscorlib.dll<span 
        style="color:blue">&lt;/</span><span style="color:#A31515">HintPath</span><span 
        style="color:blue">&gt;<br />
    &lt;/</span><span style="color:#A31515">Reference</span><span style="color:
blue">&gt;</span></span><br /><br /></li>

<li>Modify AssemblyInfo.cs and remove the following lines:<br />
<br />
[assembly: ComVisible(false)]<br />
[assembly: Guid("b5e2449f-193c-46d1-9023-9143618d8491")]<br />
<br />
</li>

<li>Modify AssemblyInfo.cs and add the following:<br />
<br />
[assembly: ScriptAssembly("ScriptSharpDemoAssembly")<br />
<br />
</li>

<li>Ensure it compiles in Visual Studio</li>
<li>Create a batch script or PowerShell script that compiles using ssc.exe like this:<br />
<br />
..\Libs\ScriptSharp\v1.0\ssc.exe ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/debug ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/out:MyScriptSharp.js ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;/ref:"..\Libs\ScriptSharp\v1.0\Framework\mscorlib.dll" ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;.\Properties\AssemblyInfo.cs ^<br />
&nbsp;&nbsp;&nbsp;&nbsp;.\Class1.cs<br />
<br />

</li>
</ol>

<p>Notice the last two lines in the script are a list of the files that you want to include.  The point of this exercise is that you can now include files outside of your main Script# project in that list.</p>
<p>Now for completeness if you put a simple static method in Class1.cs, something like this:</p>
    <p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;color:blue;mso-ansi-language:EN-US;mso-fareast-language:EN-US;
mso-bidi-language:AR-SA">namespace</span><span style="font-size:9.5pt;
line-height:115%;font-family:Consolas;mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;mso-ansi-language:EN-US;mso-fareast-language:
EN-US;mso-bidi-language:AR-SA"> MyScriptSharp<br />
        {<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">class</span> <span style="color:#2B91AF">Class1<br />
        </span><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>{<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">static</span> <span style="color:blue">string</span> 
        HelloWorld()<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:blue">
        return</span> <span style="color:#A31515">&quot;Hello World!&quot;</span>;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>}<br />
        }</span></p>

<p>Then run the batch file you should get something like this:</p>

<p><span style="font-size:9.5pt;line-height:115%;
font-family:Consolas;mso-fareast-font-family:Calibri;mso-fareast-theme-font:
minor-latin;mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:
AR-SA">Type.registerNamespace(<span style="color:maroon">&#39;MyScriptSharp&#39;</span>);<br />
    <br />
    <span style="color:darkgreen">
    ////////////////////////////////////////////////////////////////////////////////<br />
    // MyScriptSharp.Class1<br />
    <br />
    </span>MyScriptSharp.Class1 = <span style="color:blue">function</span> 
    MyScriptSharp_Class1() {<br />
    }<br />
    MyScriptSharp.Class1.helloWorld = <span style="color:blue">function</span> 
    MyScriptSharp_Class1$helloWorld() {<br />
    <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>
    <span style="color:maroon">&#39;Hello World!&#39;</span>;<br />
    }<br />
    <br />
    MyScriptSharp.Class1.registerClass(<span style="color:maroon">&#39;MyScriptSharp.Class1&#39;</span>);</span></p>

<p>Obviously you could get these results faster with approach #1.  But now you have a lot more control.</p>

<p><b>Summary</b></p>

<p>The main downside to this approach is maintaining the batch file is a bit of a hassle.  But the upsides are that you can include any file from your server-side C# code.  And any changes in that server-side code are automatically reflected in your JavaScript.  And any breaking changes in your server-side code generate compile time errors in your client side code.  And furthermore none of your team members need to install Script#.  For our team it's an easy tradeoff.  What about for yours?  Please share your thoughts in the comments or on <a href="http://twitter.com/#!/lprichar">twitter</a>.</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/lee_richardson/integrating_javascript_and_c_w.html</link>
            <guid>http://www.nearinfinity.com/blogs/lee_richardson/integrating_javascript_and_c_w.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">script#</category>
            
            <pubDate>Tue, 23 Aug 2011 23:09:48 -0500</pubDate>
        </item>
        
        <item>
            <title>Web Performance v. Usability</title>
            <description><![CDATA[<p>Looking through the web for standards on how to make your web pages more performant (i.e. using tools like <a href="http://developer.yahoo.com/yslow/">YSlow!</a>), one of the things that is mentioned is to put your css at the top and your javascript at the bottom.  The reason to do this is so that your content will render faster (and be styled) and not have to wait for the parsing of the javascript in order to display.</p>

<p>Recently I have been getting into using <a href="http://www.jqueryui.com">jQuery UI</a> a lot more.  I like the common look and feel, the ability to theme it easily, and am excited for all of the new enhancements and widgets that are coming.  The issue that I have found is that when jQuery UI initializes your widgets it adds the theming classes from the javascript.  This causes the page content to render (in a very ugly unstyled fashion) and then it "pops" into the nice styled page.  As a user also, I tend to hate this effect and find it very annoying.  So I set out to see what I could do to fix this and still keep the site performant.</p>

<h2>First attempt - pure <span class="caps">CSS</span></h2>

<p>At first I thought, well what if I just put the jQuery UI classes on the elements that I know will already receive those classes when jQuery UI ran?  This worked well for some of the page but there were still issues:</p>


<ol>
<li> Some of the jQuery UI widgets add in extra <span class="caps">DOM </span>elements to accomplish the look they are going for, so this still had the jumping effect</li>
<li> I was now bound to a specific version of jQuery UI because if they ever changed or tweaked their class names I would have to update all of my elements with the changes</li>
<li> By adding the classes on the server I increased the page size and content that needed to be downloaded to the browser</li>
</ol>




<h2>Second attempt - rearrange the JS</h2>

<p>Since the <span class="caps">CSS </span>way wasn't ideal and would cause a lot of maintenance I decided to see what would happen if I rearranged where I loaded the <span class="caps">JS. </span> I put all of the JS back in the head tag, so it would load (and parse) the JS before any content would display to the user.  This solution was better, however, there was still a little jumping of the page before it was fully styled.</p>

<h2>Third attempt - tweaking the JS calls</h2>

<p>Finally, I took a look at how I was calling the jQuery UI widget initializers.  I found that I was calling them inside of jQuery(window).load call.  I then did some research and realized that the difference between jQuery(window).load and jQuery(document).ready is actually pretty significant if you have a lot of images.  This is due to the fact that window load waits for the images to finish before being called where as document ready is called when the <span class="caps">DOM </span>is finished loading.  Changing those calls to be inside of a jQuery(document).ready block did the trick and the page loads without any jumping.</p>

<p>So from this exercise I found that as the web world moves towards more and more javascript based <span class="caps">UI'</span>s we will need to look more closely at these blanket performance statements and include usability in those measurements.</p>

<h2>Extra nugget:</h2>

<p>The pages in question above also load various content through ajax after the page loads.  I found a small performance gain when I kept the jQuery UI initializers in the document ready block and moved the ajax calls into the window load block.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/chris_rohr/web_performance_v_usability.html</link>
            <guid>http://www.nearinfinity.com/blogs/chris_rohr/web_performance_v_usability.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">jquery</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">jquery-ui</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">performance</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">usability</category>
            
            <pubDate>Tue, 28 Jun 2011 13:04:53 -0500</pubDate>
        </item>
        
        <item>
            <title>Both Scale and Crop an Image using Javascript and CSS</title>
            <description><![CDATA[
<script type='text/javascript' src='http://www.nearinfinity.com/blogs/assets/jcato/scripts/prototype.js'></script>

<script>

var imageData = {
  kittah: {  width:900, top:-175, left:-165, url: 'http://www.nearinfinity.com/blogs/assets/jcato/images/Kittah.jpg' },
};

var Croppenscaler = Class.create();
Croppenscaler.prototype = {

  initialize: function(options) {
    var image = imageData[options.image];

    this.url = image.url;
    this.frameHeight = options.height || 400;
    this.frameWidth = options.width || 300;

    var scale = this.frameWidth / 300;

    this.imageWidth = (image.width) * scale;
    this.positionTop = (image.top) * scale;
    this.positionLeft = (image.left) * scale;
  },

  buildFrame: function() {

    var img = new Element('img',{src:this.url, 'class':'zoom'});
    img.setStyle({
      width: this.imageWidth+'px',
      top: this.positionTop+'px',
      left: this.positionLeft+'px',
    });

    var frame = new Element('div',{'class':'croppenscaler'});
    frame.update(img);
    frame.setStyle({
      height:this.frameHeight+'px',
      width:this.frameWidth+'px',
    });

    return frame;
  },
};

var loadImages = function() {
  $('cats').insert(new Croppenscaler({image:'kittah'}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:400,height:250}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:200,height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:100,height:150}).buildFrame());
}

document.observe('dom:loaded',loadImages)
</script>

<style>
  .entrybody img { max-width: none; }

  .croppenscaler {
    display: inline-block;
    overflow: hidden;
    border: 1px solid #000;
    margin: 1.5px
  }

  .croppenscaler img {
    position: relative;
    border: none;
  }
</style>

<p>
A common CSS problem is the need to crop and scale an image on a page. Scaling an image is easily done using the hight and width attributes of the image. Likewise cropping an image can be accomplished by using the image as a background of an element and setting the hight and width of the element. Both scaling and cropping an image is a bit more involved however, and if it's something that's done often it pays to have a class that handles the creation of cropped and scaled images. For this purpose I've written the Croppenscaler.
</p>

<p>
The idea here is to create a div element with a set size that has a nested div within that displays a relatively positioned image. I found that it was useful to have a hash of image data that defines the default size and crop position of an image. These values are adjusted when the frame is built so that no matter what scale the resulting frame has, the image is positioned in the same place.
</p>

<h3>CSS Classes</h3>

<p>
Let's examine the nessessary CSS classes first:
</p>

<pre class='prettyprint'>

  .croppenscaler {
    display: inline-block;
    overflow: hidden;
  }

  .croppenscaler img {
    position: relative;
    border: none;
  }

</pre>

<p>
  The important attributes to note above are the use of overflow on the main croppenscaler, this ensures that the top frame has the intended size. The nested image is positioned relatively. All of the other CSS attributes are written in the style attribute because they have to be calculated when the frame is built.
</p>

<h3>The Croppenscaler Class:</h3>

<p>
  The javascript below uses the Prototype framework, but it could just as easily use JQuery or raw javascript to accomplish the same thing.
</p>

<pre class='prettyprint'>

var imageData = {
  kittah: {  width:900, top:-175, left:-165, url: 'http://www.nearinfinity.com/blogs/assets/jcato/images/Kittah.jpg' },
};

var Croppenscaler = Class.create();
Croppenscaler.prototype = {

  initialize: function(options) {
    var image = imageData[options.image];

    this.url = image.url;
    this.frameHeight = options.height || 400;
    this.frameWidth = options.width || 300;

    var scale = this.frameWidth / 300;

    this.imageWidth = (image.width) * scale;
    this.positionTop = (image.top) * scale;
    this.positionLeft = (image.left) * scale;
  },

  buildFrame: function() {

    var img = new Element('img',{src:this.url, 'class':'zoom'});
    img.setStyle({
      width: this.imageWidth+'px',
      top: this.positionTop+'px',
      left: this.positionLeft+'px',
    });

    var frame = new Element('div',{'class':'croppenscaler'});
    frame.update(img);
    frame.setStyle({
      height:this.frameHeight+'px',
      width:this.frameWidth+'px',
    });

    return frame;
  },
};

</pre>

<p>
The class has two functions. The constructor takes a hash of options for the resulting frame; the image key and the height and width of the frame. In this version the constructor references an imageData hash to get the details about the image to display, but they could be passed into the function as well. The important thing is that the constructor has access to the height and width of the frame, as well as the default width of the image and the top and left attributes that define where the upper left corner of the image should be when it's displayed at its default width.
</p>

<p>
The buildFrame() function takes the calculated sizes and uses them to construct the frame div, with a nested image at a scale that fits within the frame, and positioned the same at any scale.
</p>

<p>
Then to use the class, create a new Croppenscaler with a hash that at least includes the image key, and an optional height and width, call the buildFrame() function and insert the resulting element onto the page.
</p>

<pre class='prettyprint'>
var loadImages = function() {
  $('cats').insert(new Croppenscaler({image:'kittah'}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:400,height:250}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:200,height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:100,height:150}).buildFrame());
}
</pre>

<p>
The above code will then produce the clowder of cats below.
</p>

<div id='cats'></div>
]]></description>
            <link>http://www.nearinfinity.com/blogs/john_cato/both_scale_and_crop_an_image_u.html</link>
            <guid>http://www.nearinfinity.com/blogs/john_cato/both_scale_and_crop_an_image_u.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">CSS</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
            <pubDate>Sun, 08 May 2011 11:17:42 -0500</pubDate>
        </item>
        
        <item>
            <title>CoffeeScript Slides</title>
            <description><![CDATA[ <p>Today is the <a href="http://www.nearinfinity.com">Near Infinity</a> Spring Conference. We have one conference in the fall and one in the spring for all our developers as well as invited guests. Today I gave a presentation on <a href="http://coffeescript.org">CoffeeScript</a> and shared the slides <a href="http://www.slideshare.net/scottleber/coffeescript-7642999">here</a>.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/coffeescript_slides.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/coffeescript_slides.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">coffeescript</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">javascript</category>
            
            <pubDate>Fri, 15 Apr 2011 15:19:06 -0500</pubDate>
        </item>
        
        <item>
            <title>Exporting an ExtJs GridPanel to Word XML</title>
            <description><![CDATA[This blog post will lay out some of steps for exporting an ExtJs GridPanel to Word XML.&nbsp; This is useful if you want to save or print what's currently displayed in the grid.&nbsp; I am writing a subsequent post with steps on how to actually generate a Word XML file, but for now I'll focus on defining a grid, getting the grid's state, sending the grid's state to a controller, and prompting the user to save the generated Word XML document.<br /><br />Technologies used:<br />- Ruby on Rails<br />- mod_xsendfile for Apache2/Apache2.2<br />- ExtJs<br />- javascript<br /><br />At a high level, the following happens:<br />1. Gather and send the GridPanel state/configuration to the controller.<br />2. The controller runs a query and generates Word XML based on the query results.<br />3. The Word XML file is presented to the user via an "Open/Save As" dialog using XSendFile.<br /><br /><font style="font-size: 1.25em;"><b>Section 1: Getting the current state/configuration of the GridPanel</b></font><br /><br />If you're familiar with ExtJs GridPanel's you know they can be configured by each user viewing the panel.&nbsp; Columns can be added, removed, grouped, shortened, lengthened and repositioned.&nbsp; To capture the GridPanel's current state and pass it to the exporter, I wrote the following javascript.&nbsp; It calculates and returns an array containing the column order, which column data indexes belong to which titles, the grouped field (if any), the sorted field, the sorted direction, and the widths of each column.&nbsp; You will see where this function is used when I define the GridPanel in the next section.<br /><br /><br />
<pre class="prettyprint">var prepareExport = function(gridStore, gridColumnModel) {<br />&nbsp;&nbsp;&nbsp; var sort = null;<br />&nbsp;&nbsp;&nbsp; var direction = null;<br />&nbsp;&nbsp;&nbsp; if (gridStore.getSortState()) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sort = gridStore.getSortState().field();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; direction = gridStore.getSortState().direction;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var columnOrder = []; //ordered list of columns reflecting the GridPanel's state<br />&nbsp;&nbsp;&nbsp; var columnsToTitles = {}; //map of ext field mappings to column titles<br />&nbsp;&nbsp;&nbsp; var columnsToWidths = {}; //width of each column<br />&nbsp;&nbsp;&nbsp; var totalWidth = 0;<br />&nbsp;&nbsp;&nbsp; var groupByField = gridStore.groupField; //the store's current grouping field ('false' if not grouped)<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var storeReaderMapping = gridStore.fields.items;<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //check to see if the groupField has a corresponding mapping<br />&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; gridReaderMapping.length; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (gridReaderMapping[i].name == gridStore.groupField &amp;&amp; gridReaderMapping[i].mapping != null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; groupByField = gridReaderMapping[i].mapping;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //get the total width of the displayed columns (this will be used later when generating the Word XML)<br />&nbsp;&nbsp;&nbsp; gridColumnModel.getColumnsBy(function(c) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!c.hidden) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; totalWidth = totalWidth + c.width;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //iterate over the grid's column model.&nbsp; For displayed columns, get the ext field names (mappings) and column titles<br />&nbsp;&nbsp;&nbsp; gridColumnModel.getColumnsBy(function(c) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!c.hidden) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; gridReaderMapping.length; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (gridReaderMapping[i].name == c.dataIndex &amp;&amp; gridReaderMapping[i].mapping == null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnOrder.push(gridReaderMapping[i].name);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var key = gridReaderMapping[i].name;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToTitles[key] = c.header;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToWidths[key] = c.width/totalWidth;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (gridReaderMapping[i].name == c.dataIndex &amp;&amp; gridReaderMapping[i].mapping != null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //if the name and mapping are different (i.e. a mapping exists), we need to push the mapping and not the name<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnOrder.push(gridReaderMapping[i].mapping);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var key = gridReaderMapping[i].mapping;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToTitles[key] = c.header;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToWidths[key] = c.width/totalWidth;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; return [columnOrder, columnsToTitles, groupByField, sort, direction, columnsToWidths];<br />};</pre><br /><br /><br /><font style="font-size: 1.25em;"><b>Section 2: The GridPanel</b></font><br /><br />Here's a basic ExtJs GridPanel.&nbsp; Note the "exportButton" is defined in Section 3.<br /><br /><pre class="prettyprint">var gridReaderMapping = [<br />&nbsp;&nbsp;&nbsp; {name: 'id'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_one'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_two', mapping: 'some_mapping'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_three'}<br />];<br /><br />var gridColumnModel = new Ext.grid.ColumnModel({<br />&nbsp;&nbsp;&nbsp; defaults: {sortable: true},<br />&nbsp;&nbsp;&nbsp; columns: [<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'ID', dataIndex: 'id'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column One', dataIndex: 'col_one'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column Two', dataIndex: 'col_two'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column Three', dataIndex: 'col_three'}<br />&nbsp;&nbsp;&nbsp; ]<br />});<br /><br />var store = new Ext.data.GroupingStore({<br />&nbsp;&nbsp;&nbsp; proxy: new Ext.dataHttpProxy({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; url: 'give/me/my/data'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; method: 'GET'<br />&nbsp;&nbsp;&nbsp; }),<br />&nbsp;&nbsp;&nbsp; reader: new Ext.data.JsonReader({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; root: 'data',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; totalProperty: 'total',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; messageProperty: 'message'<br />&nbsp;&nbsp;&nbsp; }, gridReaderMapping)<br />});<br /><br />var grid = new Ext.grid.GridPanel({<br />&nbsp;&nbsp;&nbsp; id: 'gridpanel',<br />&nbsp;&nbsp;&nbsp; ds: gridStore,<br />&nbsp;&nbsp;&nbsp; cm: gridColumnModel,<br />&nbsp;&nbsp;&nbsp; sm: new Ext.grid.RowSelectionModel({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; singleSelect: true<br />&nbsp;&nbsp;&nbsp; }),<br />&nbsp;&nbsp;&nbsp; tbar: [exportButton],<br />&nbsp;&nbsp;&nbsp; view: etc, etc, etc, etc...<br />});</pre><br /><br /><font style="font-size: 1.25em;"><b>Section 3: The Export Button</b></font><br /><br />When the export button is clicked it gathers all the necessary data from the GridPanel (columns, widths, etc) and passes that data along with query parameters to the controller.&nbsp; The controller runs a query and generates the Word XML file.&nbsp; Section 4 describes what happens when the Ajax request returns the data successfully.<br /><br />As I said at the beginning of this post, I will follow on with another post about the actual Word XML generation.&nbsp; The Word XML generation isn't too scary.&nbsp; If you're impatient, here are a few tips on Word XML generation.<br />&nbsp;&nbsp;&nbsp; 1. You can start by creating a small Word XML file with a single table using MS Word or Open Office.&nbsp; <br />&nbsp;&nbsp;&nbsp; 2. Open the XML file with the XML viewer/editor of your choice.&nbsp; Your table will be buried somewhere between &lt;w:body&gt; and &lt;/w:body&gt;.&nbsp; All the other sections of the XML can remain the same.&nbsp; <br />&nbsp;&nbsp;&nbsp; 3. You can create a series of templates for Word XML tables and rows based on the patterns you see in your Word XML sample.<br />&nbsp;&nbsp;&nbsp; 4. In your Word XML generator, substitute values into these templates to build tables.<br />&nbsp;&nbsp;&nbsp; 5. Insert the generated templates into a "master" template. <br /><br /><pre class="prettyprint">var exportButton = new Ext.Button({<br />&nbsp;&nbsp;&nbsp; renderTo: this.wrap,<br />&nbsp;&nbsp;&nbsp; listeners: {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; click: function (node, event) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var exportConfig = prepareExport(grid.getStore(), grid.getColumnModel());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Ext.Ajax.request({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; url: 'url/to/query/for/data'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; params: {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnsToTitles': Ext.util.JSON.encode(exportConfig[1]),<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnsToWidths': Ext.util.JSON.encode(exportConfig[5]),<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnOrder[]': exportConfig[0],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupByExport': exportConfig[2],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupBy': gridStore.groupField,<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupDir': 'ASC',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'sort': exportConfig[3],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'dir': exportConfig[4],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'export': true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'query': build_some_query_params_to_pass_to_the_controller<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; success: function(response, opts) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; window.location.href = 'path/to/exporter_controller/export_word_XML'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; failure: function(response, opts) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //output error message<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; scope: this<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }); <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />});</pre><br /><br /><font style="font-size: 1.25em;"><b>Section 4:&nbsp; Downloading the Word XML</b></font><br /><br />Using XSendFile to prompt the user with an "Open/Save As" dialog box.<br /><br /><pre class="prettyprint">class ExportController &lt; ApplicationController<br />&nbsp;&nbsp;&nbsp; def export_word_XML<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filename = "#{X_SENDFILEPATH}/word_doc.xml"<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (File.exist?(filename))<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; send_file filename, :x_sendfile =&gt; true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; render :nothing =&gt; true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end<br />&nbsp;&nbsp;&nbsp; end<br />end</pre><br />Stay tuned for the upcoming Word XML <b><i>generation</i></b> blog post!<br />]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/exporting_an_extjs_gridpanel_t.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/exporting_an_extjs_gridpanel_t.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Ruby</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
            <pubDate>Sun, 06 Mar 2011 16:43:27 -0500</pubDate>
        </item>
        
        <item>
            <title>Lessons Learned Building an HTTPS Everywhere Safari Extension Clone</title>
            <description><![CDATA[<p>Ever since hearing about <a href="http://codebutler.com/firesheep">Firesheep</a> I've wanted a Safari extension similar to the <a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a> extension for Firefox. Frankly, I was puzzled that one didn't already exist, so I set out to write it. The result is <a href="http://www.nearinfinity.com/home/opensource/ssl-everywhere.html">SSL Everywhere</a>. The journey is this blog post.</p>

<p>I started the project as an effort to protect myself and others from Firesheep when using Safari on an open public wireless network, much like those found in coffee shops, hotels, and airports everywhere. Firesheep works by <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Session_hijacking">hijacking your session</a>, which is basically a way of stealing your active login without needing your username or password. </p>

<p>My goal with SSL Everywhere was to protect someone from a session hijacking attack by ensuring all requests to the originating website were tunneled through SSL. This seemed trivial until I thought about the various kinds of requests that would need to be secured.</p>

<ul>
<li>the original HTML page</li>
<li>images</li>
<li>external JavaScript files</li>
<li>external CSS files</li>
<li>inline frames (iframes)</li>
<li>object or embed tags for things like videos or applets</li>
<li>Ajax requests</li>
<li>requests for the favicon</li>
</ul>

<p>It wasn't until I started to tackle each of the list items that I realized just how limited Safari's extension API is, and ultimately that <strong>one could never build a foolproof extension to protect Safari users from session hijacking attacks</strong>.</p>

<h1>Lessons Learned</h1>

<p>If you've spent any significant time writing Safari extensions, you may already be aware of the many restrictions and challenges I wrestled with for hours. Much of what I learned was trial and error, despite <a href="http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/Introduction/Introduction.html">well written documentation from Apple</a>. While the documentation does a fair job of describing many of the things you can do with an extension, it doesn't provide as much detail on what you <em>can't</em> do. That's what you'll find below.</p>

<h2>No Access to Raw Cookies</h2>

<p>The key to avoiding a session hijacking attempt is making sure the attacker can't access the session cookie, or cookies, your browser sends on each request. This can obviously be done by making sure all requests take place over an SSL connection. Unfortunately, you can't guarantee this won't happen since Safari extensions have no opportunity to intercept webpage requests before they occur. A user could easily type http://twitter.com into their address bar and SSL Everywhere couldn't stop the request.</p>

<p>The other option I pursued was having SSL Everywhere attempt to mark session cookies as secure since the browser will not send cookies marked as secure over a non-SSL connection. However, a Safari extension has no additional ability to manipulate cookies than normal JavaScript running on a page, meaning there is no way to read a cookie's path or expiration date for example. So, there's no way for the SSL Everywhere extension to simply mark a cookie as secure without having to guess at, or omit, other cookie information which may be important to the operation of the website.</p>

<h2>No beforeload for favicons, Ajax Calls, or Stylesheet References</h2>

<p>Apple was responsible for adding the beforeload event to Webkit. This gives scripts (and extensions) the ability to decide whether an external resource should be loaded or not. As stated in the Safari Extensions Development Guide, </p>

<blockquote>
  <p>Safari 5.0 and later (and other Webkit-based browsers) generates a "beforeload" event before loading each sub-resource belonging to a webpage. The "beforeload" event is generated before loading every script, iframe, image, or style sheet specified in the webpage, for example.</p>
</blockquote>

<p>I was thrilled after reading those two sentences because it was exactly what I needed. That is, until I discovered there's no beforeload event fired when the browser requests a website's favicon, makes an Ajax request, or loads an image reference defined in a stylesheet. This leaves a loophole where I can't stop a non-secure favicon reference, Ajax call, or CSS image reference from exposing the session cookies I can't properly mark as secure.</p>

<h2>src Attribute Can Not be Changed in beforeload Event Handlers</h2>

<p>I ultimately wanted to have a beforeload event listener that would </p>

<ol>
<li>inspect the source URL being requested</li>
<li>rewrite the source URL to a secure https: version if necessary</li>
<li>replace the resource's insecure reference with the secure https: URL</li>
<li>allow the loading of the resource to proceed with the new, secure URL</li>
</ol>

<p>Following the above procedure results in the resource being requested with the SSL-secured URL as desired, but will not stop the original load with the original, insecure, URL. You just end up making two requests for the same resource; one over SSL, the other not. Again, another point of exposure for the cookies.</p>

<h2>beforeload != before request</h2>

<p>It turns out that all the effort described above to leverage the beforeload event was futile. Preventing a resource from loading, as described in Apple's example of <a href="http://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW9">blocking unwanted content</a>, stops it from being inserted into the DOM, but does not prevent it from being requested by the browser anyway.</p>

<p>Apple's example documentation states</p>

<blockquote>
  <p>If your script responds to a "beforeload" event by calling event.preventDefault(), the pending sub-resource is not loaded. This is a useful technique for blocking ads...</p>
</blockquote>

<p>Should I have really expected that "the pending sub-resource is not loaded" doesn't imply that it's not requested? Perhaps I wasn't sharp enough to catch that nuance, but once again the cookies are exposed.</p>

<h2>Host Page Prototypes Can Not be Changed</h2>

<p>When I discovered the beforeload event doesn't fire on Ajax requests, I decided to try to override the XMLHttpRequest <code>open</code> method and rewrite any insecure URLs to a secure version before yielding to the original <code>open</code> implementation. What I found was that you can't modify the prototypes of the page your start or end scripts are being injected into.</p>

<p>I suspect this has something to do with start and end scripts being secluded in their own separate, and randomly named, namespace. Changing around object prototypes never resulted in any errors, it just didn't change the prototypes of the host page and therefore couldn't change the XMLHttpRequest object. Again, another point of exposure for the precious cookies.</p>

<h1>Status of SSL Everywhere</h1>

<p>If you've read this far it should be obvious that SSL Everywhere cannot guarantee protection against session hijacking attacks, including those from Firesheep. However, it does enhance security by automatically redirecting you to secure versions of many websites and rewriting insecure links to their SSL-encrypted equivalents. If you must use Safari to access popular websites when connected to an open WiFi network, you're probably better off doing it with SSL Everywhere.</p>

<p>We don't offer a pre-built version of the extension for easy installation into Safari because we don't want people to casually install it and forget that it's not completely secure for all sites. If people find it valuable nonetheless, then we may consider creating the extension bundle in the future.</p>

<h1>Try It!</h1>

<p>If you'd like to try SSL Everywhere you can find the <a href="https://github.com/nearinfinity/ssl-everywhere.safariextension">source code on Github</a>. It's open source software licensed under the GPL version 2 license, primarily because it borrows code from <a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a>. If you can come up with solutions to any of the problems I encountered, please let me know!</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/jeff_kunkle/lessons_learned_building_an_ht.html</link>
            <guid>http://www.nearinfinity.com/blogs/jeff_kunkle/lessons_learned_building_an_ht.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Mac OS X</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Security</category>
            
            
            <pubDate>Tue, 14 Dec 2010 08:31:55 -0500</pubDate>
        </item>
        
        <item>
            <title>Announcing JS Boot Camp! JavaScript Proficiency in Just Two Days.</title>
            <description><![CDATA[<p>Near Infinity is proud to announce that Chris Williams will debut his
new JavaScript Boot Camp classes here at the Near Infinity
Training Center February 10th and 11th. The JS Boot Camp is designed to
take developers from being interested in JavaScript to proficiency in
just two days.</p>

<p>JS is the scripting language that powers the web and increasingly it
is becoming critical for many tasks outside of the browser.
Unfortunately, many people, possibly you, are not yet proficient in
this highly usable and very important programming language. Maybe you
have dabbled with a JS library like jQuery or Prototype, but you now
want to understand what is going on and why. Perhaps you program
Python, Ruby, PHP, Perl or another language and making your
application rich and interactive on the web has you befuddled. Perhaps
you are a program manager and you want your design and development teams
to communicate better with one another Whatever the reason, now is the
perfect time to learn JS properly and this is the class for you. As Chris puts it, "if you need to ask whether you should take this class or not", you probably should.<br /></p>Chris also promises to provide the attendees with an awesome and hard-to-come by <a href="http://www.joyent.com/">Joyent</a> <a href="http://no.de/">no.de</a>
 account and all the knowledge of how to use it. You will easily be the 
envy of all your friends, colleagues, and most of the development world.<br /><br />

<p>The JS Boot Camp will be taught by Chris Williams, the originator the
popular <a href="http://jsconf.us/2011/">JSConf</a> JavaScript conference, the first real JavaScript
conference. Chris is also the producer of <a href="http://www.aminutewithbrendan.com/" target="_blank">A Minute With Brendan</a> and <a href="http://jsconflive.com/" target="_blank">JSConfLive.</a></p>

<p>To learn more and to register please visit the <a href="http://jsbootcamp.com/" target="_blank">JSBootcamp</a> web site.</p>

Be sure to check out our <a href="https://www.nearinfinity.com/trainingcenter/coursecatalog/upcoming/">Upcoming NIC-U Training Courses</a> page for future courses including Android classes in January and February. ]]></description>
            <link>http://www.nearinfinity.com/blogs/gray_herter/announcing_jsbootcamp.html</link>
            <guid>http://www.nearinfinity.com/blogs/gray_herter/announcing_jsbootcamp.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">javascript</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">joyent</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">jquery</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">jsconf</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">node.js</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">prototype</category>
            
            <pubDate>Thu, 09 Dec 2010 10:40:00 -0500</pubDate>
        </item>
        
        <item>
            <title>Selenium Mojo : Protoype Bindings in Selenium</title>
            <description><![CDATA[<font style="font-size: 1.25em;"><b>Introduction</b></font><br /><br />On my current project we have been involved in converting some of the hundreds of manual tests that are run by our Test Team every release into a suite of automated Selenium RC tests.<br /><br />During the course of this adventure my crew found several instances where XPath and native JavaScript were not sufficiently expressive to find elements in some of our more complicated interfaces. <br /><br />Since our web app uses the Prototype/Scriptaculous JavaScript framework we wanted to find a way to make the locating power of Prototype available within Selenium RC.<br /><br />We developed approaches for both Selenium 0.9.2 and Selenium 1.0.3 (which had better programmatic support for adding JavaScript user extensions to Selenium).<br /><br /><br /><font style="font-size: 1.25em;"><b>Selenium 0.9.2</b></font><br /><br />Selenium RC provides the capability to add "user extensions" to augment its JavaScript core. <br /><br />See <a href="http://seleniumhq.org/docs/08_user_extensions.html">http://seleniumhq.org/docs/08_user_extensions.html</a> for detailed information on how to set this up. <br /><br />We wrote the following user-extension.js file:<br /><br /><pre class="prettyprint">Selenium.prototype.setupProtoypeJS = function() {<br />&nbsp;&nbsp;&nbsp; id = selenium.browserbot.getCurrentWindow().$;<br />&nbsp;&nbsp;&nbsp; css = selenium.browserbot.getCurrentWindow().$$;<br />}</pre><br />In our code we have a base class for all our test cases. To this we added our own waitForPage() method:<br /><br /><pre class="prettyprint">public void waitForPage() {<br />&nbsp;&nbsp;&nbsp; selenium.waitForPage('60000')<br />&nbsp;&nbsp;&nbsp; proc.doCommand('setupPrototypeJS', [])<br />}</pre><br />Thus every time the page reloads (which clears the JavaScript context) we call waitForPage() and this command is re-executed. It creates two global variables (id and css) and binds them to Prototype's $ and $$ functions respectively.<br /><br /><i>Note: The reason we choose id and css instead of $ and $$ was that Groovy considers $ in Strings to be a special character and we would have had to escape it each time it was used</i>.<br /><br />The Prototype selectors can now be used in Selenium RC like this:<br /><br /><pre class="prettyprint">selenium.click("dom=id('foo')")<br />selenium.click("dom=css('.bar')")<br />selenium.click("dom=css('span.foo a.baz')")</pre><br /><i>Note: You still have to specify the dom locator type so Selenium RC will know to execute your locator string as JavaScript.&nbsp; <br /></i><br /><br /><font style="font-size: 1.25em;"><b>Selenium 1.0.3</b></font><br /><br />In more recent version of Selenium RC the project added the setExtensionJs() method. This allows you to set extension JavaScript programmatically prior to starting the selenium client:<br /><br /><pre class="prettyprint">selenium = new DefaultSelenium(...)<br />selenium.setExtensionJs('...')<br />selenium.start()</pre><br />This made it much easier to implement our Prototype bindings. The only trick was that the JavaScript seems to be executed prior to having access to a page context and is also only executed once. This required us to take a different approach.<br /><br />We created id and css as global functions instead of variables. This allowed us to defer accessing the current window until the functions were actually invoked. &nbsp; <br /><br /><pre class="prettyprint">selenium.setExtensionJs('''<br />        id = function(value) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    return selenium.browserbot.getCurrentWindow().$(value);<br /><div id=":w0" class="ii gt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; css = function(value) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return selenium.browserbot.<wbr>getCurrentWindow().$$(value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />''');</div></pre> <br /><i>Note: The above code snippet is written in Groovy which allows multiline Strings.<br /></i><br />The Prototype selectors are used in Selenium RC like before:<br /><br /><pre class="prettyprint">selenium.click("dom=id('foo')")<br />selenium.click("dom=css('.bar')")<br />selenium.click("dom=css('span.foo a.baz')")</pre><br /><br /><br />I would be interested in hearing feedback from anyone who has a chance to use this technique!<br />]]></description>
            <link>http://www.nearinfinity.com/blogs/stephen_mouring_jr/selenium_mojo_protoype_binding.html</link>
            <guid>http://www.nearinfinity.com/blogs/stephen_mouring_jr/selenium_mojo_protoype_binding.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Testing</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
            <pubDate>Sat, 24 Apr 2010 14:00:36 -0500</pubDate>
        </item>
        
        <item>
            <title>JavaScript Particle Engine in Canvas</title>
            <description><![CDATA[<p>The most popular entry I've written at Near Infinity has been the <a href="http://www.nearinfinity.com/blogs/page/jharwig?entry=javascript_particle_engine">JavaScript Particle Engine</a>.  It had limitations because I used transparent images and only made one color -- black. I recreated the fire demo for a talk -- Advanced Web Graphics with Canvas -- that I gave at the <a href="http://therichwebexperience.com/conference/speaker/jason_harwig.html">Rich Web Experience</a>. I'll post the slides, sample code, and some more demos in upcoming entries.</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/javascript_particle_engine_in_canvas.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/javascript_particle_engine_in_canvas.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
            <pubDate>Tue, 23 Sep 2008 19:24:23 -0500</pubDate>
        </item>
        
        <item>
            <title>JavaScript Obscured (How to confuse coworkers)</title>
            <description><![CDATA[<p>I was reading a blog entry at <a href="http://webreflection.blogspot.com/2008/06/two-simple-tricks-in-javascript-olds.html">Web Reflection</a> that outlined some obscure solutions to common JavaScript patterns.</p>

<p>I thought that entry was interesting, but I'm not sure I'd use them because of code readability and maintenance. It did get me thinking of some other ways to obscure simple tasks.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/javascript_obscured_how_to_confuse.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/javascript_obscured_how_to_confuse.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
            <pubDate>Thu, 05 Jun 2008 20:19:44 -0500</pubDate>
        </item>
        
        <item>
            <title>Server-side JavaScript and Jaxer</title>
            <description><![CDATA[<p>The web community has been buzzing about the new Ajax server, Jaxer, from Aptana. If you haven't heard see <a href="http://ejohn.org/blog/server-side-javascript-with-jaxer/">John's</a>, or <a href="http://ajaxian.com/archives/aptana-releases-jaxer-ajax-server-built-on-mozilla">Dion's Ajaxian</a> posts about it.</p>

<p>Now, overall, I am really excited about the future in this project. The problem I had is all their examples use <i>synchronous</i> XMLHttpRequests. We <a href="http://ajaxblog.com/archives/2005/05/25/synchronous-requests-bad">already</a> <a href="http://www.oreillynet.com/xml/blog/2007/01/do_sync_calls_freeze_browsers.html">know</a> <a href="http://swik.net/Ajax/Ajax-Development-Gotchas">why</a> this is unfriendly to users.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/server_side_javascript_and_jaxer.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/server_side_javascript_and_jaxer.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
            <pubDate>Wed, 23 Jan 2008 13:36:15 -0500</pubDate>
        </item>
        
        <item>
            <title>JavaScript Security Slides from No Fluff Just Stuff</title>
            <description><![CDATA[<p>I spoke at the Reston, VA <a href="http://www.nofluffjuststuff.com">No Fluff Just Stuff</a> conference again this past weekend.  The talk was on JavaScript security covering topics including:
</p><ul>
<li>Cross-site scripting (XSS)</li>
<li>Cross-site-request forgery (CSRF)</li>
<li>JSON Hi-jacking</li>
<li>JavaScript portscanning</li>
<li>JavaScript and CSS History "Go Fish"</li>
</ul>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/javascript_security_slides_from_no.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/javascript_security_slides_from_no.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Security</category>
            
            
            <pubDate>Thu, 08 Nov 2007 19:38:27 -0500</pubDate>
        </item>
        
        <item>
            <title>Testing JavaScript Objects with Function.prototype.call</title>
            <description><![CDATA[<p>This is a short tip that I found useful for testing complex JavaScript objects using <a href="http://www.thefrontside.net/crosscheck">crosscheck</a>. For more information on crosscheck see my article on <a href="/blogs/page/jharwig?entry=javascript_unit_testing">JavaScript Unit Testing with Crosscheck</a>. </p>

<p>Testing instance methods can be a pain if the functions use instance variables and the object is heavyweight. In my case the constructor did a lot with the DOM that I didn't want to mock. Instead of invoking the function through an instance of an object, I called it statically. </p>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/testing_custom_javascript_libraries_with.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/testing_custom_javascript_libraries_with.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Testing</category>
            
            
            <pubDate>Thu, 11 Oct 2007 18:33:31 -0500</pubDate>
        </item>
        
        <item>
            <title>JavaScript Unit Testing with Crosscheck</title>
            <description><![CDATA[<p>Here we are, a couple years since Ajax was coined, JavaScript has become a language that people actually respect. The code being written now is better than ever before. Object-orientation, name-spacing, object detection, and correct scoping are prevalent now. The libraries available (prototype, jquery, yui, dojo) are very well written. What is the next step to improve code quality? If you want my opinion, it's Testing. Otherwise, <a href="http://www.digg.com">here's</a> the door. :) </p>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/javascript_unit_testing.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/javascript_unit_testing.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Testing</category>
            
            
            <pubDate>Mon, 08 Oct 2007 15:08:12 -0500</pubDate>
        </item>
        
        <item>
            <title>Prototype.js Documentation Site Launched</title>
            <description><![CDATA[<p>It seems that <a href="http://encytemedia.com/blog/articles/2007/1/18/prototype-1-5-released-and-documentation-site-live">Encytemedia</a> was successful in their <a href="http://encytemedia.com/blog/articles/2006/10/31/prototype-a-call-for-documentation">"Call for Prototype Documentation"</a> blog posted in the old year.

</p><p>The site lives at <a href="http://prototypejs.org">prototypejs.org</a> and should help new and experienced users alike master the popular JavaScript library.

</p><h3>Features</h3>

<ul>
<li>API of all extended and new objects with examples</li>
<li>Tips/Tutorials section that includes how prototype works</li>
<li>Easy method for users to contribute</li>
</ul>

<p>Good work guys!</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/jason_harwig/prototype_js_documention_site_launched.html</link>
            <guid>http://www.nearinfinity.com/blogs/jason_harwig/prototype_js_documention_site_launched.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
            
            <pubDate>Thu, 18 Jan 2007 17:37:44 -0500</pubDate>
        </item>
        
    </channel>
</rss>

