On her good side

Doing a Life / Relationships tag today because I have done way too much development and documentation review to want to do anything else technical. I think if you were to ask my wife or any of her friends, they would say I am one of the better husbands in the world – of course I think if you asked any of my friends I think the term they would use is ‘whipped’. Be that as it may, once in a while I will post a couple of things I have done in the past that got good reception in case there are some readers out there that want some ideas to earn some extra brownie points from their significant other. Life should be about more than just coding and work so make sure you put some effort into your relationships too, it makes work that much more enjoyable having that balance in place.

So here are a few good ideas for you. Feel free to steal them entirely and take all the credit – I promise not to tell.

Compliment Stones

goodside1

I actually got this idea from RedEnvelope a few years ago. I think it is a great idea but some of the sayings are a little cheesy or at least a little impersonal since they really aren’t your words. What I did was take some nice polished stones; we actually already had some from a vase in one of our rooms but feel free to get some from a craft store. You can then get some clear Avery labels and print out your own sayings. If I recall I had some mushy ones, some funny ones and some that were a bit risqué – but be creative and make sure to have some that would only make sense to the two of you which will make it more personal. You can then place them in a small gift box or container with all the messages face down or place them in a nice velvet pouch with a drawstring. Then write up a little note with some instructions such as “each morning or when you need a little pick me up, pick up a stone, read it and then put it back”.

Fortune Cookies

goodside2

Another spin on the idea that I did last year was Fortune Cookie messages. My wife loves fortune cookies, I don’t even think she likes the taste of them but loves the surprise of the messages. I found this metal fortune cookie set standing in line at Borders where they have all the compulsive shopping items. It also came with a bunch of tear-away pre-written message but I just printed out my own messages on clear labels and stuck them to the strips and whited out the other side. I couldn’t find the actual kit online anywhere but I found the container which is all you need here. I gave her a message every day for a month and then it just turned into a once in a while thing. You can also use them for apologizing if needed.

Scavenger Hunt

Working for a consulting company, I am lucky to not have to travel as much as I used to but there are certainly times when I have had to head out for an extended time. When I had to go to London for 2 weeks for VW Credit back in 2007, I bought a few trinkets and gifts for my wife and the kids and I hid them around the house. I then hid clues to those hiding spots throughout the house. Then each day when I would call them to say goodnight I would give them a clue to where they would find a clue to one of their gifts. This took a lot of planning and you end up running out of hiding spots if you are gone for too many nights but I think it was worth it because after the greeting hugs at the airport one of the first things my son said to me was “Hey, Dad when do you have to go out of town again so we can have another scavenger hunt”.

Mac Goodness on a PC

Being a Microsoft centric developer you can assume correctly that I am also a PC guy. That is not to say that I am anti-Apple – actually I have 2 iTouches, a shuffle, a Nano and an iPad but I have not dumped my PC for a Mac yet. But there are some nice features a Mac has that aren’t out of the box with a PC. Here are 3 of my favorite things to install on your PC to make it a bit more user friendly.

Google Quick Search Box

If you go to http://www.google.com/quicksearchbox/ to install the Quick Search Box you will see a nice disclaimer that says “Requires Mac OS X 10.5 Leopard+”. You see Google Quick Search Box used to be for Windows too but got discontinued in early 2010. Back then I was already hooked on the search box so I quickly found this blog post that walks through installing the discontinued software. Basically you can install an older version of the Google Toolbar, copy the Quick Search Box application to another location and then you can uninstall the old Google Toolbar and the QSB will stay.

Windows does have their own search within the Start Window but I find the search to be a bit slow and doesn’t take into my previous interaction. If I search “e” for Evernote I get the below screen. Of course if I type “ev” then Evernote comes up but the next time I search and type “e” I still get the below screen instead of it knowing that I wanted Evernote last time and displaying it first.

macgoodness1

Below is the same use case only with Google’s QSB. It knows I went to Evernote that last time I entered an “e” and it lists it first. So to quickly bring up Evernote, I just have to type [Alt]+[Space Bar], “e”, [Enter]. Windows has shortcut keys of [Windows] + [0 – 9] for quick launch which is nice but will only support your 10 apps you have pinned to your task bar.

macgoodness2

VirtualWin

I came across this program when I was pairing with a developer that was working on a Mac and with a couple key strokes he would jump back and forth between a number of different desktops depending on what we were working on. I loved it. I am not sure what it was called on his Mac, it might just be part of the OS but I did find a program that did the same thing for Windows. It is called VirtualWin. It allows you to setup up to 9 virtual windows and then quickly jump from one desktop to another, even if you have a dual monitor you might find this program useful.

ObjectDoc

When I used my mouse more and thought bubble animations were cool I used ObjectDoc for a while. I don’t use this now but it is a good program and to stick with today’s theme of making our PC more Mac like this program is right up that alley.

macgoodness3

I am sure there others out there as well, so let me know if you have a favorite tool you use on your PC to make it a bit more user friendly. If you want to go all out you can get a White Apple Sticker and stick it over your Dell logo.

Scripting out Monotony with AHK

I posted previously about reducing the use of your mouse to speed up your daily computer work (not just development). I wanted to elaborate a bit more on Auto Hot Key (AHK) that has been around since 2003 but I don’t run into a lot of people that use it.

Wikipedia
AutoHotkey is a free, open source macro-creation and automation software utility which allows users to automate repetitive tasks. Any application user interface can be modified by AutoHotkey (for example, with Emacs style).[2] It is driven by a custom scripting language that is aimed specifically at providing keyboard shortcuts or hotkeys.

Before Windows 7 came out I had an AHK script that would allow me to arrange a window to take up 1/2 the left or right side of my monitor with a quick keyboard command. Of course the ‘Snap Feature’ is now part of Windows 7 but AHK allowed me to easily build one of the main features Microsoft promoted during their Windows 7 campaign – I do have to point out in the commercial the guy is using the mouse to drag the 2 windows to the side instead of [Win Key]+[Left Arrow] then [Alt]+[Tab] then [Win Key]+[Right Arrow] which would be faster 🙂

Microsoft took care of the snap feature for verticle tile placement but sometimes I like to have a window snapped to the left but take up more than 50% of the screen area. This allows me to have more area for my document but still have the ability to see part of my desktop on the right in case I were using Sidebar Gadgets or in this case my Sticky Notes. If you look at the screenshot below, you can see that my Posterous editing window at 50% leaves very little room for my Rich Text Editor.

ahk1

So let’s create a script that will Snap my window to the Left and then make it a bit wider.

The first thing we will download and install AutoHotKey from here.

We then want an .ahk script in our Startup folder so our commands are available when Windows starts. It can be blank for now.

Next we want to download a AHK macro recorder here (written with AHK scripting) that will record keystrokes and mouse movements and generate AHK scripting for us so we don’t have to code as much from hand. As you get familiar with AHK you will need the Recorder less and less but it will be your friend when you are fist starting out.

I am a big fan of Continuous Improvement both in development and life. As time goes on we are going to want to add or maintain some of our short cuts. I am at the point now (after using it for 7 years) that my brain automatically says “Hey James, you have already done this combination of steps 3 times this week” and I open up my .ahk file and assign the steps to a shortcut key. There is no sense in making it difficult to edit, build or record our AHK scripts so the first thing you will see in my script are 3 shortcuts to do just that.

ahk2

Reviewing AHK documentation or using the Macro recorder you will notice that “<” is Left and “!” is the [Alt] key. So above you can see that when I do a [Left Alt]+Z, notepad will open up my AHK script. [Left Alt]+X will execute my .ahk script to take into account any changes I just made. [Left Alt]+C will open up the Macro Recorder. There are also text editor’s that have color coding and intellisense for AHK scripts that you could use instead of Notepad but I haven’t installed them since the last time I rebuilt my laptop.

So now that we have those 3 key hot keys assigned let us do a [Left Alt]+C so our Macro Recorder will open.

ahk3

To create our ‘Wider Left Window Snap’ functionality we will do something like the following narrative:

  1. Hit Start on the Recorder (this will minimize the recorder so it is not with focus)
  2. [Windows] + [Left] combo which snaps my current window to the Left.
  3. Click the right border of the window and drag it so the window is at the size you like.
  4. [Ctrl] + [Shift] + [End] to stop the recorder

Here is what our recorded script looks like.

ahk4

One thing to notice is that we aren’t quite done because our recorder doesn’t do a good job at recognizing drag and drop, so we are going to have to script that part by hand. What we can quickly do is record once more and click on the area of the screen that is where our right window border. This will give us the coordinates we need for our drag and drop action. I also updated the script to use the #{Left} instead of the LWin and LWin Up functionality because it is cleaner. So our finished script looks like below.

ahk5

For simpler scripts you can have everything all on 1 line, but here we have a 6 line block not including the comments. Here is the breakdown:

  • #.:: – # is the Windows key so if the user clicks {Windows}+{Period} then this script block will fire. I used the period key because it has a “>” key above it and I am adjusting the window to the right and the greater than sign is like a Right arrow. You could assign this script block to whatever hotkey combination you like.
  • Send, #{Left} – The script will send the {Windows}+{Left Arrow} to the system which will Snap the window to the Left
  • Click, 686, 305, Left, down – This is the first part of our drag and drop. We are telling the script to go to x686,y305 and hold down the Left mouse button
  • Click, 1078, 305, Left, 0 – Here we are dragging our mouse to the x1078,y305 position
  • Click up – release the Left mouse button
  • return – finish the script block

We can then {Ctrl}+S to save our .ahk script, then {Ctrl}+X to rebuild the script. Now when in any window and a {Win}+{Period} is struck the current window will quickly resize to a position like below.

ahk6

What else?

Start simple and then expand on your script. I would suggest putting in words or phrases that you type a lot throughout your week. Sure there are plug-ins for your browsers that can fill in your address information but they don’t work across other applications so I have quick hot keys for a lot of my contact information. Below you can see some of them.

ahk7

So now I can quickly type in phone numbers, passwords, usernames whatever else with 2 key strokes (Right Alt and then a letter or number). Yes storing passwords and credit card information in plain text isn’t the best idea but I figure if someone has access to my hard drive to read this file then I have a bigger concern.

There are also Hot Strings too which are cool. Instead of using a key combination to run a script, AHK will monitor your key combinations and when it finds a match it will replace the combination with what is specified. I use this for email addresses and words I often mistype.

ahk8

So any time I type “j@” it will be replaced with my work email and if I do “c@” it will be my gmail address. If I accidentally type “teh” it will correct to “the”. I also have the scripts below that will navigate up/down 5 lines at a time and left/right words at a time. This makes me quickly navigate with the keyboard.

ahk9

You know enough now to get creative. For example I have a script where with a quick key combination; I launch Google Chrome, go to sirius.com, open up their Listen Player and ensure the station is on Alt Nation. Now I just need a script that will post a new and insightful Blog Post with a quick key stroke.

Filtered Search Sample (part 4 – search service)

  • In Part 1 we talked about interacting and consuming the search service
  • In Part 2 we discussed a Tagging strategy to allow for a Filtered Search to be possible
  • In Part 3 we looked at our service layer which worked with our Ajax calls
    Screen1

Today we are going to dive into our search service and talk about some of the customizations we did to make Lucene and Sitecore do what we wanted from an Indexing and Search standpoint. If you recall from Part 3 (or by looking at the above screenshot) we had a piece of code that would create a new Searcher and call the GetItems method passing in the SearchParams we created based on the Ajax call that was being executed. Now we are going to dive into what the Searcher class is.

Screen2

Our Searcher class is just a modified version of the code that you can get from Sitecore’s Shared Source library and you can watch a webinar to get more detail on it here so I won’t go into a lot of detail. Instead I will just go over some of the modifications I have made. Above you can see that we have an additional call to an ApplyTagFilter method that will help us filter by the Tags that were checked by the user in our UI.

Screen3

The ApplyTagFilter method will iterate through the GUIDs in our Tag collection and add them as an OR criteria to our query. Seeing how that our Tags are GUIDs and therefore unique you will notice we are just querying against the BuiltIn.Content field.

Indexing

Screen4

So the AdvancedDatabaseCrawler is inheriting from the standard Sitecore DatabaseCrawler. One requirement our client had is that they want the ability to hide an item from search fairly easily even if the actual content is available on the site. The way I accomplished this is to simply have a Field on the Base Page Template called “Hide From Search”. Keying off of this field we can then tell Sitecore to not index the item if this field is checked.

Screen5

When setting up the configuration for each index you can specify the boost, but I have taken it a step farther here allowing the Content Managers to overwrite the Boost associated with the Template or Page.

Screen6

So above we are taking the default Boost associated with the document based on the configuration and adjusting it with the Search Boost value if the field exists.

Screen7

If you look at the article above it is tagged as a White Paper. If the user does a search for items that are tagged as an Article / White Papers then this article wouldn’t actually come up in our results because the White Paper GUID is different than its parent. We could dynamically bubble up a Tag’s ancestry at Query time but that would be a little bit of a performance hit so instead we are going to crawl up the Tag hierarchy with the crawler. You can see how we are doing this below.

Screen8

 

Debugging

When you are setting up your custom crawler and doing some tricky things with searches you will inevitably need to figure out why-in-the-heck you are not getting the results you are expecting. The best way to do this is to set a break point at the point where your code is about to call RunQuery and copy the LuceneQuery value. Once you have this query you can use the Luke client or Sitecore Rocks VS.NET Plug-in to run the query and see why it is not pulling back what you are expecting.

Screen9

It’s a Wrap

Well it took four posts, but hopefully you got a good understanding of the approach we used for Filtered Search on a recent project. If you want to learn a bit more, there is a great webcast for the Sitecore Virtual User Group in July that has a great overview and some samples as well. Lucene is quite fast and for future projects I will probably take it a step further where we can leverage Lucene for more than just Search and Filtered Search and use it for presentation elements as well such as menus, lists and summaries.

 

 

Filtered Search Sample (part 3 – service layer)

In Part 1 we talked about interacting and consuming the search service. In Part 2we discussed a Tagging strategy to allow for a Filtered Search to be possible. Today we are going to look at the service layer that is called by the presentation layer.

SearchService.cs

Screen1

Here we have the method signature that is called by the client. So as we went over in Part 1, if the user searches for “cost savings” and selects the Industries of “Construction” and “Energy” the following url is used in the Ajax call on the client end.

htttp://www.domainname.com/Services/SearchService.svc/SearchInsightsJson?&Category2={017E7503-83A1-4A45-9053-4C6755715162}|{66310DCB-3BD1-4C4C-9AFA-FBBC8D4BA967}&page=1&perPage=8&searchString=cost%20savings

This url ends up calling the SearchInsightsJson method within the SearchService web service class and it will pass in the GUIDs associated with Construction and Energy, the current page the user is on, the results the client wants per page the searchString is set to “cost savings”.

You will notice the method has two attributes that mark the method as an OperationContract (available via the web service) and the WebGet attribute is stating that the response should be in a JSON format.

Prevent Client-side Caching

Screen2

The three lines of code above help prevent any caching that may occur by the client. Technically because the url would be unique for each search request we could remove this block of code all together with little impact but this ensures if a new item has been published since the client ran the query that it would get picked up in the search results.

Building-up the Criteria

Screen3

The code shot above shows the approach to calling the Search service. We are populating a SearchParam object with the information needed by the Search Service to run the query.

  • LocationIds = the top folder or folders within the CMS we want to search.
  • TemplateIds = the page types we want included in our search.
  • FullTextQuery = the key word or phrase the user entered in the search form.
  • ShowAllVersions = this specifies if we want to search all versions of a page or just the latest
  • Language = sets the language context of our search (for multi-lingual sites)

We then check each Category parameter and if it is not null we will add the pipe delimited GUIDs to the Tags collection.

Search Call and Setup Paging

Screen4

The first piece is calling our Search Service and passing in our Criteria. We can then set some parameter values that we will include in our JSON result so our presentation can provide paging functionality without having to do the logic on their end.

We set the TotalResults is set to the hits.Count and the CurrentPage is the page that was passed in originally so the client doesn’t have maintain state.

The results we get back from the Search Service is actually just a List of what we are calling a SkinnyItem, that is to say, it is just a pointer to the actual Item along with some other meta data. SkinnyItem has a GetItem() method that will retrieve the full Item from Sitecore but if we have 1000+ items that match our search and we truly only need to fetch the ones that are being displayed on the current page (8 of them), it would be a lot of unnecessary overhead to do this.

We end up creating an s and an e variable that we will use in the next code snippet. e is either going to be (perPage * page) or the total results from the search whichever  is less. s is either ((perPage * page) – perPage) or the hits.Count – perPage whichever  is less (as long as it is >= 0).

Screen5

Above we are iterating through the SkinnyItems between our s and or e count and grabbing the full Item out of Sitecore in order to populate a SearchResultItem and add it to our resultItems collection. This seems like an extra step because we are going from a SkinnyItem to get a Sitecore Item to get a SearchResultItem but there is a logical reason. The SkinnyItem is essentially a representation of the raw search result from Lucene. The Sitecore Item is acting as full data record or Domain Object and the SearchResultItem is a simple Data Transfer Object containing only the fields needed by the view.

We set the JSON resultData.Results equal to the collection of SearchResultItems we just created and we set the TotalPages equal to the total records divided by items per page and round up.

We set the SearchUrl with the value that was passed in and provide it back to the client so it doesn’t have to worry about state.

The PageStart is what the starting page in the page navigation should be. This is hard coded right now with a paging of 5 but this could come from a config file or even the CMS. This allows our client to setup paging of 6 through 10 when a current page of 7 is passed in (see below).

Screen6

Next Up

So that is what our web service looks like. While writing this blog post and taking screenshots I see some areas of improvement and refactoring but you should get the idea of what the service layer should be doing. Part 4 will focus on our actual Search service. This will go into detail about how we customized our Crawler, setup our Indexes and leveraged the advanced searcher / crawler from the Sitecore Shared Source library – if you want to get a heads start on that I recommend this video.

Filtered Search Sample (part 2 – tagging structure)

For the second part of the Filtered Search Sample we are going to look at the data layer to support our Filtered Search presentation. The implementation here is being implemented with Sitecore as the data store but the pattern could easily be some other CMS or just a database.

Tagging

Screen1

Our filtering is based on searching across the repository for items that have the criteria we are looking for. This requires two basic things. The first being our items need to be tagged in some fashion and the second is that those tags are made available to the user to include or exclude from the results. Above you can see that we have a hierarchical tagging structure. This allows nested tags such as an Article and a White Paper can have the same parent and then we can allow the parent of “Article / White Paper” be used in the Filtered Search.

You can also see that a Tag is more than just a string field. This allows us to associate a Tag with an icon and a description if we want. The PowerFilter property of the Tag is what we are using to tell the system if we want the Tag to be listed in the Filtered Search module. We are using Tags for a lot more than just the FilteredSearch so this field allows us to flag the Tag as an item we want the user to be able to filter on.

Configuration

Screen3

Here you see we have a configuration element in Sitecore that allows a content manager to specify the title, the instructions, how many results should be displayed per page and which Tag Categories should be used.

View

Screen2

The PowerFilter Sublayout is just an .ascx User Control that inherits from the SublayoutBase – if you are not familiar with Sitecore it is merely a base class that makes it easier to get access to the context in which the control is being used. Here we are setting the context of control to the PowerFilter item we just discussed. We are binding an ASP.NET Repeater to the Tag Categories chosen and we actually have a repeater within a repeater that will list out each Tag within the Tag Categories if it’s PowerFilter property is set to true.

Next Up

We have covered the presentation and now the tagging structure we setup using Sitecore; next we will go into implementing the service layer that will respond to the Ajax calls that actually get the results to be displayed.

Filtered Search Sample (part 1 – clientside)

I think we did a pretty nice implementation of site search on a recent project. It made effective use of jQuery, AJAX calls and a flexible service and data layer.

Search1

Filtering allows the user to quickly widdle down the number of assets on a site to a more manageable result set. The Filter/Search area can be shown or hidden by the user and allows the user to quickly view documents and assets that are located on the site that fit the user’s criteria. The area is available throughout the site and persists state so the user can quickly view their last result

Search2

Above is the view of the filter search when adding criteria and clicking “View Results”

Search Form

The html is presenting a set of checkboxes grouped by their parent category. The values of each tag is the corresponding GUID that exists in the data layer. The parent category check-box simply checks or unchecks it’s children when selected or unselected.

Screen1

View Results Click

Our Javascript will leverage jQuery and iterate through the checkboxes and use the keyword value to build a url to call through Ajax and and get a JSON result set to populate the result div.

Screen2

AJAX Call / Response

Using Firebug we see what we are getting back from the Ajax call. You can see that we passed in 1 tag for the 2nd category and 1 tag for the 3rd category, the user did not enter in a keyword (searchString) and the results we want per page is 8. The results we get back will be a JSON collection. For performance reasons we have paging occur on the serverside so although there are 35 items that match our criteria we only get back 8 (based off of the perPage parameter). Each JSON object contains what we need to show the results – the link, the icon, the name and the snippet (if exists).

Screen3

Display the results

Screen4

 

Our jQuery.getJSON function will iterate through the result set and create a div resultBlock for each item. One little tricky thing you will see above is that our results are actually split across 2 columns so we have a check to see if the current item in the for loop is equal to the perPage / 2 and creating a new column if that is the case.

Next Up

So we just went over the clientside of the fence for calling and displaying the results, tomorrow I will go over how this was handled on the serverside using C# and Sitecore as our datalayer.