Probable Gotcha

The path to PortableGit looks like it has a changeset in the folder name which means that if you update Github for Windows, that path might change. This is dumb, however, I don’t believe Github for Windows will update if you never open it. So, never open it.

]]>Use SlowCheetah for Web.config transform previewshttp://eli.eliandlyndi.com/2013/09/27/slowcheetah-web-config-transform-previews/
Fri, 27 Sep 2013 16:12:45 +0000http://eli.eliandlyndi.com/?p=254I’m only two years late to this game, but I finally needed to use web.config transforms on a project. Scott Hanselman has a helpful post on it.
]]>Don’t put ng-app and ng-view on the same element.http://eli.eliandlyndi.com/2013/09/25/put-ng-app-ng-view-element/
Thu, 26 Sep 2013 00:19:22 +0000http://eli.eliandlyndi.com/?p=249Continue reading →]]>I was having a problem where Angular’s routing system wasn’t working in my application. After some experimentation I found this out:

If you have an element like

<div ng-app="app" ng-view>Stuff</div>

then links which go to known routes won’t get handled by Angular’s, rather, they just act like a normal link would. The solution was simple: put each attribute on a different element.

However, in call stacks, the code executing inside the controller’s function just shows up as (anonymous method). If I actually name the function, then it shows up as that in the call stack. So now I write it this way:

This technique works for any anonymous function in JavaScript, not just for Angular app.

]]>Navigate to URLs outside of the Angular application with target=”_self”http://eli.eliandlyndi.com/2013/08/26/navigate-urls-angular-application-target_self/
http://eli.eliandlyndi.com/2013/08/26/navigate-urls-angular-application-target_self/#commentsMon, 26 Aug 2013 22:13:28 +0000http://eli.eliandlyndi.com/?p=236Continue reading →]]>Today I brought in Angular’s routing to a view I was working on, clicked on a link which is on the same server but outside of the Angular application, and my browser’s URL updated, but the screen was just blank. Angular had hijacked the link and tried to route to the href itself.

Cache-Control: public
Expires:Fri, 15 Feb 2013 02:45:01 GMT // a year from now

and serves them.

The browser keeps the resources in its cache for a long time and future requests for them are served from cache.

You ship new code to AppHarbor. AppHarbor builds and deploys your application. It also adds a configuration setting into your web.config with a key of appharbor.commit_id and the value is set to the last changeset ID. Your server uses that changeset ID as the version identifier in static resource paths.

The browser makes a request for your homepage again. The server delivers the homepage, but this time references the static resources using the new version identifier.

The browser now must request those static resources again because the version identifier has changed. The server serves up the updated files back to the browser where they’re cached again.

Caveat: browsers will have to request all static resources again every time a build is deployed. I’m very happy to accept this. Alternatively, you could do crazy things like get a hash of the file and serve that as part of the file’s path. See Karl Seguin’s article about cache busting if you’re interested in that sort of thing.

How To Do This In Code

First, you’ll need to be able to provide static resource urls. I like to write them like this:

In the StaticContent method, I’m populating the staticResourceVersion variable from a configuration value which is in my web.config. If one is not set, like when you’re running your site locally, “_default” is provided.

The first and third routes are the default ones that come with MVC. The middle route understands how to handle requests which start with s/ followed by the version identifier and then whatever the path to the resource is. It directs those requests to the StaticsController’s Index action.

The StaticController’s Index action first needs to check if the requested path is allowed. We certainly wouldn’t want to serve just any content back through here. (I’m showing a really simple IsAllowed implementation, please feel free to be smarter about yours.)

For my own sanity, when I’m deving on my localbox, I don’t ever want content cached. So the caching headers are only set when the request is not local.

And finally, the file is served up with the correct content type. (Again, simple implementation, feel free to be smarter.)

The staticResourceVersion variable is ignored; I haven’t thought of anything to do with it yet.

And the hard work is done! Update your static resource urls to use the Url.StaticContent helper, deploy out to AppHarbor, and bask in the the glory of long-cache-expiration-headered static content.

The End

Special thanks to my fellow devs at Cheezburger for teaching me this technique.

Thanks to Michael Friis for telling me that AppHarbor inserts the commit_id into a deployed web.config.

See how the button starts dragging from the top left corner and drags really slowly? I stripped down the CSS element by element using Chrome’s dev tools and was able to isolate the problem to the -webkit-transition and box-shadow styles on the .btn class. Setting those to none fixed the problem.

]]>http://eli.eliandlyndi.com/2011/12/18/jui-sortable-bootstrap-perf-problem/feed/7Using jQuery to provide an inline confirmation on buttonshttp://eli.eliandlyndi.com/2011/10/10/using-jquery-to-provide-an-inline-confirmation-on-buttons/
http://eli.eliandlyndi.com/2011/10/10/using-jquery-to-provide-an-inline-confirmation-on-buttons/#commentsMon, 10 Oct 2011 20:22:31 +0000http://eli.eliandlyndi.com/?p=125Continue reading →]]>I was working on a side project and wanted the user to confirm when they wanted to delete something. The normal window.confirm method was just too primitive so I decided to write something I liked a little more.

Click the delete button below to see it in action. Click the JavaScript tab below to see how it works.

This was built for use with the amazing Bootstrap CSS framework. Only the classes that are added/removed are dependent on Bootstrap, so adjust to your needs.

]]>http://eli.eliandlyndi.com/2011/10/10/using-jquery-to-provide-an-inline-confirmation-on-buttons/feed/4Getting the version number of your own Chrome Extensionhttp://eli.eliandlyndi.com/2011/08/12/getting-the-version-number-of-your-own-chrome-extension/
Fri, 12 Aug 2011 19:42:37 +0000http://eli.eliandlyndi.com/2011/08/12/getting-the-version-number-of-your-own-chrome-extension/