jQuery Download Plugin

jQuery Download Plugin

I was in need of an “export” button to export some data to a CSV file, but the data changes based on some other choices. I added my js to export the file and then – DUH! You cannot use ajax to return a file. Silly me… :)

I figured I could wrap a form around the button and set a hidden input and blah blah blah. I googled and found the above, which basically does all that for me and gives me a convenient 1 liner to work much like an ajax call would but allow for a “save as” dialog. It is pretty neat-o!

jQuery finds

I just ran across a couple of cool things to solve some problems. I needed a small pub/sub solution, and I found a tiny one:

jQuery Tiny Pub/Sub

It is a pretty slick little implementation and, more importantly, helped me solve my problem.

I needed to lazy load images, and there are a few solutions out there, but I was looking for something small (do you see a theme?) and I found this:

Unveil.js

This takes a very nice lazy load plugin and strips it down to the most basic of functionality resulting in a great lazy load plugin that comes in under 1k.

MediaBrowser3

For some time I have wanted a nice media experience for playing back my music/movies. I also wanted something that would make it nice and easy to play content over the internet when I travel. I was considering just writing something from scratch just for the experience, but then I thought, “why reinvent the wheel?” and I opted for an existing media server package.

First I tried Plex. I have to say it is pretty user-friendly, but it does have its quirks. For example, certain media tags would not update properly, and no matter what I did I could not figure out how to get the “agent” (the code that fetches the metadata) to work. Also, when I wanted to extend some functionality I found out the source is closed, so that really put me off.

While looking into how I could extend Plex, I ran across info for MediaBrowser3. The codebase is in C# and it is open source (github repo), so I knew that I could do with it as I pleased. I installed it and was very pleased.

MB3 is the next version from an established MB2, so there are some things that are still in flux, but the dev community is very active. I saw a call for devs to join the team, so I did. I have always wanted to join an open source project, but I have always been a bit intimidated by the prospect as well. I have to say I am very happy I did drop them a line to join because the experience has been great and the community is fantastic – and very supportive and appreciative of all the devs! :)

Personally I have focused on a redesign of the video player interface, and recently I have started to play with the chromecast SDK to enable casting from the MB3 web client. Speaking of clients, there are many to choose from: desktop clients, mobile clients, the web client, whatever floats your boat.

If you have been in the market for a great media server, I’d suggest checking out MB3. And if you are a developer, visit the community forum and leave a message on the “join the team” post. Even if you are not a dev, there are still other ways you can support the project through documentation or language translation.

Spiffing up Calibre content server with Bootstrap

I really dig Calibre. It is great for managing my growing Kindle ebook collection. One thing I do not like about it is the chosen style of the content server. To each his own, I guess…

I thought it would be pretty cool to style it with Bootstrap. It would look pleasing to me, and since the source is available I thought I’d be able to figure it out pretty easily. The app is written in Python, but it turns out the content server uses templates (mostly anyway, there is quite a bit of generated HTML in there – ewww!)

I started poking around with the templates, and then I wondered if someone else already had the same thought. I googled and sure enough someone had. I found this post that included a gzipped tarball ready to go. I downloaded it, unzipped, copy/pasted the folders and checked it out.

I liked what I saw, but I thought it could be just a little bit better. I changed up some of the markup and got a better flow (I never liked the overflow). To limit the initial book comments I used a great plugin called readmore (with a really slick looking site too). Finally, I set up the templates to use the responsive style sheet. I did not make any edits for the mobile sizes, so things look a bit wonky, but it beats the heck out the the built-in mobile option:

Original version

Original version


With my updates

With my updates


My "Mobile" layout

“Mobile” layout

If you are a Calibre user and you’d like to use this (or the original which can be downloaded from the link) you can download the 7zip here: content_server.

To “install”, just unzip and replace the folder. On a windows PC the path is [install_path]\resources\. The folder is content_server.

UPDATE: Craig finished his initial pass at using Bootstrap 3 on put it up on GitHub. It looks great!

Introducing DataTablesDotNet

The datatables plugin is one of the coolest jQuery plugins around, and I wanted to find a way to make it work easily with ASP.NET MVC sites. Initially I created some objects that included the various datatables property names and that worked well. However, when another project came along and I wanted to use datatables in that project too I realized the original way I created the objects just wasn’t going to cut it.

After a lot of searching I found this blog post. I liked what I saw. Even better was the additional code contributed by Paul Inglis in the comments. The only thing I did not like was the stringify used to turn the datatables JSON into key/value pairs. I also did not like the way the project was made available – a box.net download location with no way to contribute (hence the code in the comments). I decided I would build on these great contributions and update the code to work without the serialization.

So, here it is on GitHub. The code has been cleaned up, it uses Paul’s Expression code for building the filters/sorts, and it doesn’t stringify the datatables data which cuts the data sent pretty much in half. I also added a model binder so it all “just works”.

NOTE: Isn’t it funny how one can look for something and not see it right in front of them? When I was doing my original googling, I was getting next to nothing for results. It is funny how that can work out sometimes. I built upon the above codebase and pushed my code to GitHub and nuget because I thought I was providing something of value. It wasn’t until I searched for my nuget package that I saw about a dozen other packages doing similar things. That being said, there are only a couple that include everything I did – others are just models or binders, so it is somewhat of use. Also, I see in the most used package a minor flaw in logic in the binder, but it doesn’t break any functionality, so not a big deal. Finally, the process gave me a chance to do a deep-dive into Expressions, and that was very enlightening, so the entire process was still of use, even if the nuget package isn’t. :)

Diff in Sublime 2

I love Sublime 2. I never thought something like Sublime would be something I’d love, but I really do. I thought, “It’s just a text editor. What is the big deal?” It is so much more than just a text editor, but it gets the majority of its use from me as one and I could not be happier.

I was recently working with some diff’ing using WinMerge, and I generated a patch file. I did not want to initially apply all the chages from the patch, but there are some pretty good code changes from the newest version of NopCommerce that I would like to add to our site, so I thought I’d cherry pick. I opened up the patch in Sublime, and too my dismay found there was no color highlighting even the the syntax selection was correct. A quick google and I found this post about editing the theme to fix the problem. Yet another thing to love about Sublime 2. Here are the steps I took to get at the theme easily and the edits I made.

  1. Select Preferences > Browse Packages – this will open up Windows Explorer
  2. Find your color scheme folder. Most likely it is named something like “Color Scheme – XXX” (e.g., “Color Scheme – Grandson of Obsidian”)
  3. Open the XXX.tmTheme file (in Sublime of course)
  4. Add entries for: diff.header, diff.deleted, diff.inserted and diff.changed
  5. Enjoy your new syntax highlighting

Here is the snippet I added to fit my theme:

<dict>
    <key>name</key>
    <string>diff.header</string>
    <key>scope</key>
    <string>meta.diff, meta.diff.header</string>
    <key>settings</key>
    <dict>
        <key>background</key>
        <string>#6699FF33</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>diff.deleted</string>
    <key>scope</key>
    <string>markup.deleted</string>
    <key>settings</key>
    <dict>
        <key>background</key>
        <string>#DD555566</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>diff.inserted</string>
    <key>scope</key>
    <string>markup.inserted</string>
    <key>settings</key>
    <dict>
        <key>background</key>
        <string>#33996666</string>               
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>diff.changed</string>
    <key>scope</key>
    <string>markup.changed</string>
    <key>settings</key>
    <dict>
        <key>background</key>
        <string>#E6DB7466</string>               
    </dict>
</dict>

What was the coolest part for me was the fact that Sublime 2 supports alpha. I had a hard time getting the colors exactly the right shade for my theme, so I tried adding alpha, an BAM! It worked. All I had to do was tweak the alpha to get the colors to fit to my liking. I think it fits in pretty well with the rest of the theme. I am super-stoked!

Untitled

Another really cool think was how easy it was to hack the theme. The link shows how to use foreground coloring, but I really wanted “highlighting”, so I wanted to use the background color. It was intuitive to assume I would simply change “foreground” to “background”, and I double-checked to be sure. I also really liked that the instant I saved the theme it was updated in my running instance of Sublime 2. Awesome!

MongoDB Contacts Demo App

I haven’t posted in a while. Work stuff hasn’t really been post-worthy, so I was struggling to find something to post about. I realized I had an old demo I whipped up that I had never posted about, so here goes…

I wanted to play around with Mongo, and I also wanted to play around with AppHarbor, so I thought I’d make a Mongo app I could push to AppHarbor. To keep it simple, I decided to make a contacts app – you know, something super useful.

App
http://mongocontacts.apphb.com/

Code
https://github.com/timhobbs/MongoContacts

It is pretty straight-forward. Check the “about” link in the app for some more details. You can play around with the demo app, but please try to keep things PG. I know, I know…

AngularJS form serialization

I have been playing around with AngularJS, and I am falling in love! We use KnockoutJS pretty extensively in our site, and while I do like KO, I think it is better suited for small enhancements rather than larger things like we do: cart management and a ship estimator, a pretty advanced checkout page, and a school address picker. These all work okay with KO, and honestly, they would probably work much better if they were designed better. Unfortunately this work was initially farmed out to some overseas contractors, and they seem to believe in the anti-KISS pattern, if that even exists…

To begin with, I started on some demos to focus on each task. I created a small ship estimator demo, then I made a small cart demo. Again, due to a really poor design, the ship estimator (which should be the easiest thing with a whopping 3 form fields) is the worse of the 2 in the current implementation. To be fair to KO, I think if the redesign I used for the demo were what we used in our live site, KO would suffice. That being said, Angular just provides more – it is a framework after all, while KO is just a library.

The latest demo is an address form with a school picker – you enter the zip code and a list of matching schools for the zip are displayed in a select list. Once a selection is made, the form fields are populated with the school address details and the fields are set to readonly.

This all works fine, but my co-worker asked if we could then submit the form via a normal HTML form submission. That got me to wondering, so I asked Google. I found a great post on the NG Google Group. The suggestion was to use hidden inputs to store values, and offered a couple ways to do so:

A) (This)

<input type="hidden" name="someName" value="someVal">

becomes

<input type="hidden" ng-init="someName = 'someVal'" 
    name="someName" value="{someName}}">

This first option … gives you the benefit of having the value in the scope and on the hidden element constantly synchronized.

B) Write a directive for hidden input types that picks up the name and value and inserts it into the scope. This is not too hard:

app.directive('input', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      if ( attrs.type === 'hidden' ) {
        scope[attrs.name] = attrs.value;
      }
    }
  };
});

This second option is nice but it won’t allow you to update the hidden field’s value if you plan to do a pure HTML form submission later (although with a little thought and $watch you could probably wire this up).

In our demo code, my co-worker and I opted for the first approach. It winds up being a bit more verbose, but it isn’t too much extra leg work and works well with the 2-way binding to keep the form values up to date.

CSS shorthand

Dustin Diaz has put together a nice guide to CSS shorthand. My personal favorite:

element {
  background: #fff url(image.png) no-repeat 20px 100px fixed;
}

Another favorite of mine is shorthand for margin/padding. I always remember the order by thinking of a clockface, but I also recently saw someone recommend “TRouBLe” (top, right, bottom, left). That may work, but I prefer the clockface (especially since that is what I have always used!)