0 Comments

I have to admit that as much as I like low-level middleware or backend development there is certain level of satisfaction when I am working on building some UI. Maybe it’s a quick turnaround of making a change and visually confirming that your gadget got a new color or displaying rounded corners, ultimately looking cooler with every run. But no matter how much time I spent refining and tweaking my CSS I could never make it look as cool as professional web design. The reason is trivial – I am no graphic artist, I am a programmer. I suck at drawing or picking colors, I mean, any 12 year old girl could do a better job than me. Plus let’s face it, CSS is the whole another world that you have to know in order to create cool web designs. When spending so much time writing Linq queries, WCF interfaces, and business logic who has time to perfect all the CSS tricks?

Hopeless? It was, until Bootstrap came along. CSS, HTML, and JavaScript library with classes describing layout and not content. “Originally created by a designer and a developer at Twitter, Bootstrap has become one of the most popular front-end frameworks and open source projects in the world” (bootstrap/about). Bootstrap library was originally developed to encourage consistency for the web design, but it became more than that. Bootstrap was so popular that web designs became too consistent to the point of boring, which started sites like bootswatch with the holy purpose of saving the web from default bootstrap. But it got even better, Bootstrap marketplace sites like wrapbootstrap or themeforest, or bootstrapmade became the next logical step in the bootstrap evolution, where you can buy a compete design for just a few bucks. No longer you have to worry about tweaking CSS to the point of insanity, instead you can concentrate on the functional aspect of the project and the result can still look amazingly cool. The idea of ready HTML templates is not new, of coarse, but I do not recall it’s even been so easy to incorporate 3rd party template into your project.

bootstrap liberator

This is why I think of a Bootstrap library like a bolt cutters tool given to me to cut free from the ball and chain of web design dryness. I can take the template drop it into the Content folder of my MVC project, make few adjustments to the view, and voila – professional looking web site with all the cool CSS eye candies.

0 Comments

When running user interface that accepts search criteria where you have to build and run query against database, would it be wonderful to support rules similar to Google advanced search rules?

Search for an exact word or phrase

"search"

Use quotes to search for an exact word or set of words on a web page. This is helpful when searching for song lyrics or a line from a book. But only use this if you're looking for an exact word or phrase, otherwise you'll exclude many helpful results by mistake.

"imagine all the people"

Exclude a word

-search

Add a dash (-) before a word or site to exclude all results that include that word. This is especially useful for words with multiple meanings, like Jaguar the car brand and jaguar the animal. 

jaguar speed –car

Regular Expressions would be perfect for this task.

And even though I am no expert on regular expressions I can certainly try.

If you think about it, the underlying task here is to take a search sentence and break it down into a list of tokens which contains individual words or phrases. One list for positive criteria with every word or phrase that began with either a ‘+’ character in front or empty space. Another list of negative tokens, this would be the words or phrases prefixed with ‘-‘ character. Anything in double quotes should be considered as single token.

To build a regular expression for matching positive and negative search criteria you must use negative look behind to see if your search keyword started with ‘-‘ character or ‘+’ character. The problem is when you use look-behind with long search expressions in double quotes it becomes a challenge to ignore everything inside the double quotes. For example for negative search you might match the word positive even though it is inside the double quotes just because it has ‘-‘ character in front of it:

+”this is a -positive search

And vice versa can match something inside negative search criteria:

-"this is negative"

So, instead of writing more complex regular expression I would cheat, i.e. replace every double quoted phrase with a temporary token first. Would use the following function:

private static Dictionary<string string> TextInDoubleQuotesToTokenList(string data, out string outputData) 
{ 
    var items = new Regex("\"[^\"]*\""); 
    outputData = data; 
    var key = 0; 
    var matches = items.Matches(data).Cast<object>()
        .ToDictionary(match => Token + key++, match => match == null || string.IsNullOrEmpty(match.ToString()) ? 
        string.Empty : 
        match.ToString().Replace("\"", "")); 
    var count = 0; 
    foreach (var match in matches) 
    { 
        outputData = data.Replace(match.Value, Token + count++); 
    } 
    return matches; 
}

This function will replace any text in double quotes with temporary token. For example:

“this is a positive” –“this is negative” one two –three

Will be replaced with:

@1 –@2 one two –three

Function also returns back dictionary of replaced strings where the key is the token like @1 or @2.

This way you do not have to worry about any characters inside the double quotes. After matching all the negative and positive criteria replace the tokens with original strings from the dictionary and you are done.

Here is what positive match function looks like:

private static List GetPositiveSearchCriteria(string data)
{
    string outputData;
    var tokens = TextInDoubleQuotesToTokenList(data, out outputData);

    var positiveSearch = new List();            
    try
    {
        var exp = new Regex("((?<=(\"(?[^\\s\"+-][^\"]+))(?=\")|(?[\\w][^,\\s\\-\\+\"]+)(?![\\w\"])", RegexOptions.CultureInvariant);
        var matchList = exp.Matches(outputData);

        if (matchList.Count == 0)
        {
            return null;
        }

        for (var i = 0; i < matchList.Count; i++)
        {
            if (!matchList[i].Success)
                continue;

            var index = i;

            var key = matchList[index].Groups["PosSearch"].Value;
            if (string.IsNullOrEmpty(key))
                continue;

            positiveSearch.Add(tokens.ContainsKey(key) ? tokens[key] : key);
        }
    }
    catch(ArgumentException)
    {
        return null;
    }

    return positiveSearch;
}

And negative:

 

private static List GetNegativeSearchCriteria(string data)
{
    string outputData;
    var tokens = TextInDoubleQuotesToTokenList(data, out outputData);

    var negativeSearch = new List();
    try
    {
        var exp = new Regex("(?<=[\\-]\"?)((?<=\")(?[^\"]+)|(?[^\\s,\\+\\-\"]+))", RegexOptions.IgnorePatternWhitespace);
        var matchList = exp.Matches(outputData);

        if (matchList.Count == 0)
        {
            return null;
        }

        for (var i = 0; i < matchList.Count; i++)
        {
            if (!matchList[i].Success)
                continue;

            var index = i;

            var key = matchList[index].Groups["NegSearch"].Value;
            if (string.IsNullOrEmpty(key))
                continue;

            negativeSearch.Add(tokens.ContainsKey(key) ? tokens[key] : key);
        }
    }
    catch(ArgumentException)
    {
        return null;
    }

    return negativeSearch;
}

This is it. Once you have both lists of positive and negative criteria you can run SQL in and not in or if you are using Linq to SQL or Entity Framework can use contains function

var positive = GetPositiveSearchCriteria(searchDetails);
var negative = GetNegativeSearchCriteria(searchDetails);

if (positive != null)
{
	searchItems = from p in searchItems
  	where positive.Contains(p.ColumnName)
    select p;
}

if (negative != null)
{
	searchItems = from n in searchItems
  	where !negative.Contains(n.ColumnName)
    select n;
}

Cheers.