Spot the web RSS 2.0
# Wednesday, February 13, 2008

You see it in Google search results and a lot of other sites that have good search functionality. When you perform a search, your words or phrases are highlighted in the search results making it easy for you to find the most relevant content.

Today I’m going to show you a simple way to add this to your website or blog so your users can find what they need in style. I think that this kind of thing should be implemented more often for how easy it is to implement.

Here we go!

The JavaScript code:

  1. function highlightOnLoad() {  
  2.   // Get search string  
  3.   if (/s\=/.test(window.location.search)) {  
  4.     var searchString = getSearchString();  
  5.     // Starting node, parent to all nodes you want to search  
  6.     var textContainerNode = document.getElementById("content");  
  7.     // The regex is the secret, it prevents text within tag declarations to be affected

  8.     var regex = new RegExp(">([^<]*)?("+searchString+")([^>]*)?<","ig");  
  9.     highlightTextNodes(textContainerNode, regex);  
  10.   }  
  11. }  
  12. // Pull the search string out of the URL  
  13. function getSearchString() {  
  14.   // Return sanitized search string if it exists  
  15.   var rawSearchString = window.location.search.replace(/[a-zA-Z0-9\?\&\=\%\#]+s\=(\w+)(\&.*)?/,"$1");  
  16.   // Replace '+' with '|' for regex  
  17.   return rawSearchString.replace(/\+/g,"\|");  
  18. }  
  19. function highlightTextNodes(element, regex) {  
  20.   var tempinnerHTML = element.innerHTML;  
  21.   // Do regex replace  
  22.   element.innerHTML = tempinnerHTML.replace(regex,">$1<span class='highlighted'>$2</span>$3<");  
  23. }  
  24. // Call this onload, I recommend using the function defined 
    // at: http://untruths.org/technology/javascript-windowonload/  

  25. addOnLoad(highlightOnLoad()); 

Now, the CSS:

  1. span.highlighted {  
  2.   background-color#161616;  
  3.   font-weightbold;  

Code explanation

First, the highlightOnLoad function checks window.location.search to see if we need to be running any of this stuff, then calls getSearchString to get a sanitized search string so that nothing funky can happen if, say, the user searches for ‘<script>’. You should really be sanitizing all search inputs at least on the back-end anyway.

Then, the highlightTextNodes function uses a regex replace on our textContainerNode’s innerHTML. The regex verifies that the text is between a > and a < (and not the other way around). Actually nice and simple!

Caveats

This may end up being a bit slow if you are doing this on a LOT of text, but for my blog text, it seems quite snappy to me. Also, the CSS does not bold text inside links, but the background color is there to make it obvious.

Wednesday, February 13, 2008 5:06:52 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
CSS | Javascript | Programming
# Tuesday, February 12, 2008

There are at least 5 ways to return data from one table which is not in another table. Two of these are SQL Server 2005 and greater only. This is a post mostly for beginners but hopefully everyone will get something out of it.

Here are the 5 different ways

NOT IN
NOT EXISTS
OUTER JOIN
OUTER APPLY (2005+)
EXCEPT (2005+)

Let's see how this all works
First create these two tables with the Celko approved naming convention.

 

CREATE TABLE #testnulls (ID INT)

INSERT INTO #testnulls VALUES (1)

INSERT INTO #testnulls VALUES (2)

INSERT INTO #testnulls VALUES (null)

 

CREATE TABLE #testjoin (ID INT)

INSERT INTO #testjoin VALUES (1)

INSERT INTO #testjoin VALUES (3)

NOT IN
Run the following Code

 

SELECT * FROM #testjoin WHERE ID NOT IN(SELECT ID FROM #testnulls)

What happened? Nothing gets returned! The reason is because the subquery returns a NULL and you can't compare a NULL to anything

Now run this

SELECT * FROM #testjoin

WHERE ID NOT IN(SELECT ID FROM #testnulls WHERE ID IS NOT NULL)

That worked because we eliminated the NULL values in the subquery

This also works

SELECT * FROM #testjoin j

WHERE j.ID NOT IN(SELECT ID FROM #testnulls n WHERE n.ID = j.ID)

 


NOT EXISTS
NOT EXISTS doesn't have the problem that NOT IN has. Run the following code

 

SELECT * FROM #testjoin j

WHERE NOT EXISTS (SELECT 1

FROM #testnulls n

WHERE n.ID = j.ID)

Everything worked as expected


LEFT and RIGHT JOIN
Plain vanilla LEFT and RIGHT JOINS

 

SELECT j.* FROM #testjoin j

LEFT OUTER JOIN #testnulls n ON n.ID = j.ID

WHERE n.ID IS NULL

With a RIGHT Join you just switch the tables around

SELECT j.* FROM #testnulls n

RIGHT OUTER JOIN #testjoin j ON n.ID = j.ID

WHERE n.ID IS NULL

 

And we can also do a full outer join

SELECT j.* FROM #testnulls n

FULL OUTER JOIN #testjoin j ON n.ID = j.ID

WHERE n.ID IS NULL

AND j.ID IS NOT NULL


You might wonder why we have LEFT and RIGHT Joins, here is why:
<AttemptToBeFunny>LEFT joins are for people who tend to vote for the democrats, RIGHT joins are for people who tend to vote for Republicans. FULL Joins are for independents/undecided people. </AttemptToBeFunny>

You can be real silly and do a subquery LEFT join
 

SELECT j.* FROM #testjoin j

LEFT OUTER JOIN (SELECT ID FROM #testnulls ) n ON n.ID = j.ID

WHERE n.ID IS NULL

 

Now let's talk about SQL 2005 and up

OUTER APPLY (SQL 2005 +)
OUTER APPLY is something that got added to SQL 2005

SELECT j.* FROM #testjoin j

OUTER APPLY

(SELECT id FROM #testnulls n

WHERE n.ID = j.ID) a

WHERE a.ID IS NULL

 

EXCEPT(SQL 2005 +)
EXCEPT is something that got added to SQL 2005. It basically returns everything from the top table which is not in the bottom table

 

SELECT * FROM #testjoin

EXCEPT

SELECT * FROM #testnulls


I am also mentioning INTERSECT since some people might not have seen it before. INTERSECT returns what ever is in both tables(like a regular join)

 

SELECT * FROM #testjoin

INTERSECT

SELECT * FROM #testnulls

 

So there you have it, most likely you already know all these types of joins. If you learned something from this post that is a good thing also.

Tuesday, February 12, 2008 5:05:36 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [1] - Trackback
Programming | SQL
# Sunday, February 10, 2008

It was all going so smoothly. Jason Whittington, Mark Smith and I were teaching the big DevelopMentor event here in Los Angeles (Guerrilla.NET) when my presentation on the ThreadPool took a nose dive. It started with a great joke involving Wilson (the volleyball from Cast Away).

Wilson and I built an application to compute a multiplication table where each computation was (artificially) slow. To speed it up we threw it at the thread pool using delegate.BeginInvoke. We figured that the ThreadPool would allocate 25 or so threads and the table would display quickly. Here's the expected output - pretty much the same thing we've seen since about .NET 1.0:

    

Each color represents the thread that did that computation.

For the last 7 years, the behavior has been that as the ThreadPool was overloaded, it would steadily start up new threads at the rate of one every 500 milliseconds until it hits its upper limit (typically). Using Performance Monitor (perfmon) we can watch the thread pool adding threads. It usually looks something like this:

    

Much to our surprise we saw completely different behavior. The thread pool added the first 15 or so threads quickly (as expected) but then stalled. New threads were not created every 500ms, instead they were added at increasingly long intervals. My demo took almost twice as long to run as it had the last time I did this demo a few months ago.

Jason, Mark, and I took this code, ported it back to .NET 1.1 and ran it side-by-side with .NET 3.5 and here's what we saw (blue = 3.5, red = 1.1):

    

As of .NET 3.5 the upper limit of the ThreadPool was increased: Knew that.

But, it appears that v3.5 of the CLR changes the policy for adding threads to the thread pool. Rather than adding threads regularly when under load the thread pool uses a logarithmic backoff. My colleague Jason Whittington remarked that this behavior looked similar to the behavior of the thread pool in "Rotor" (the shared-source version of the CLR). We speculated that this backoff algorithm makes sense given the new 250-thread per CPU maximum - it would take a long time to reach that if the runtime waits longer and longer to start a new thread. The 250-thread limits makes it less likely that your application will deadlock the thread pool, and the exponential backoff algorithm keeps the thread pool from creating too many threads too quickly.

Why should you care? Usually you won't, but it could have dramatic impact if you count on that behavior. For example, in our contrived case, .NET 1.1 ran about twice as fast as .NET 3.5 ( ! ):

    

Here's the program and source code (trimmed down to run in both .NET 1.1 and 3.5).

    Math.zip (6.38 KB)

Sunday, February 10, 2008 5:03:47 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [3] - Trackback
.Net | Programming | Visual Studio
Navigation
Archive
<February 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Guy Levin
Sign In
Statistics
Total Posts: 63
This Year: 0
This Month: 0
This Week: 0
Comments: 14
Themes
All Content © 2010, Guy Levin