Archive for February, 2011

I've been playing with search engines and for the search API I'm going with Bing; Google limits their free API to 100 queries a day and requires creating a custom search engine. Bing requires signing up and getting an "AppID" but from there it's unlimited. Documentation is, well, Microsoftian: impossible to find and hard to use when you get it, but there's a PDF (!) that explains things pretty well. I decided to do everything on the server rather than being fancy with AJAX; the user has to wait either way and usually wants to leave the current page anyway (that's why he's searching!). Continue reading ‘A Search Box for the Website’ »

I'm not a fan of having to create a Google Custom Search Engine to limit searches to one site with an HTML form (which seems to be necessary for mobile sites), so let's play with Bing:


<form method="get" action="http://www.bing.com/search" >
	<input name="q" type="text"/>
	<input type="submit" value="Search with Bing"/>
	<input name="q1" value="site:http://bililite.nfshost.com/blog" type="hidden"/>
</form>

And it works, but fails again on the mobile site, just like Google. This may get better as the search engines figure it out, but I'm going to have to write my own search engine portal. What a pain.

Actually, not such a pain. Something like:

header('Location: http://www.bing.com/search?q='.urlencode($_GET['q']).'+'.urlencode($_GET['q1']))

for Bing and

header('Location: http://www.google.com/search?q='.urlencode($_GET['q']).'+site:'.urlencode($_GET['sitesearch']))

for Google. And that's what I did for the Young Israel site

Earlier, I noted that the old, simple Google search:


<form method="get" action="http://www.google.com/search" >
	<input name="q" type="text"/>
	<input type="submit" value="Search with Google"/>
	<input name="sitesearch" value="http://bililite.nfshost.com/blog" type="hidden"/>
</form>

is deprecated and doesn't work from Google's mobile site. Google does have an API for custom searches that has all sorts of fancy parameters to manipulate, but it requires signing up for a key and constructing the search ahead of time. However, some experimentation shows that not including a key brings back the old, simple search query (with a new URL and some new parameters), so we're back in business:


<form method="get" action="http://www.google.com/cse" >
	<input name="q" type="text"/>
	<input type="submit" value="Search with Google"/>
	<input name="as_sitesearch" value="http://bililite.nfshost.com/blog" type="hidden"/>
</form>

And there's all sorts of interesting things hidden in there, like sorting by date (Google tries to guess that, but doesn't do so well):


<form method="get" action="http://www.google.com/cse" >
	<input name="q" type="text"/>
	<input type="submit" value="Search with Google"/>
	<input name="as_sitesearch" value="http://bililite.nfshost.com/blog" type="hidden"/>
	<input name="sort" value="date:d" type="hidden"/>
</form>

And the entire Web Search API is deprecated, so I'll have to change the googleSearch widget to use the JSON Custom Search API eventually.

Overall, sweet. At least until Google changes things again.

Addendum: it looks as though the mobile site does require the cx parameter to limit the search to a specific site. Oh, well. It's not that hard to create a custom search.

For the search on the Young Israel site, I use Google with a form that creates links like http://www.google.com/search?q=foo&sitesearch=http://youngisrael-stl.org to limit the search to the one site. It works fine in normal browsers, but on my iPhone it detects the browser and changes it to a mobile-optimized site that ignores the sitesearch=http://youngisrael-stl.org and returns results for the whole web. http://www.google.com/search?q=foo+site:youngisrael-stl.org works fine, but I can't make an HTML form add the site: term automatically. A workaround would be to make my own page on the server that mangles the query string and changes Location, but I'm not sure it's worth the effort. I'll see how many complaints I get.

Addendum, later the same day: It looks as though Google isn't supporting the sitesearch query at all; it was deprecated a few months ago. The fact that it still sometimes works is just a lucky coincidence. They use "Custom Searches" now, and this wise person figured out how to use it with forms rather than javascript. So that's what I'm using now. It serves ads at the top of the page, but I'm too cheap to pay for the ad-free version.

The documentation for the query parameters is pretty complete, and it looks as though you could create a "generic" all-web custom search then use the parameters to limit it programmatically. Unfortunately, it looks as though the XML/JSON data is only available to paying customers.

I decided to make the Young Israel site iPhone-friendly, and there are lots of good sites for tips on creating custom CSS for the small screen. The best I found was on CSS wizardry. It doesn't focus on the how so much (using media queries or checking the User-Agent string (evil!)) as the what—making sure the elements are linear vertically, not using floats, shortening headers, etc. The major problem is that his CSS sample has the "wrong" syntax for the media query, so it won't work.

The big gotcha from the official CSS3 documentation: @media (max-device-width: 480px) doesn't work (in either Safari or Firefox), even though the documentation says it's legal. You have to have a media type in there: @media screen and (max-device-width: 480px). Took me forever to find that bug.

I would also use max-device-width rather than max-width; the user on a big screen may shrink the window and it would be confusing for the layout of the site to suddenly change. I would also not use the only screen hack that Apple suggests; there doesn't seem to be any reason to use CSS hacks (shades of the 1990's!) to target only iPhones.

The other gotcha is with my CSS parser: the javascript is run in the order that it is seen, so if you want to remove a widget for the small screen you have to explicitly destroy it:

#q {
  -jquery-googleSearch: /* default */;
}
@media screen and (max-device-width: 480px){
  #q {
    -jquery-googleSearch: destroy;
  }
}

Hope this helps somebody avoid a miserable morning.

Well, jQuery 1.5 is out and there's yet another incompatibility: they changed the way attribute selectors work. You used to be able to use them without quotes, as [attr=value] but that now throws an exception. Now you have to use [attr="value"]. Not sure why they changed it; The CSS level 3 definition is ambiguous about when you need quotes, and it may be that jQuery is OK with leaving the quotes off for simple (letters/numbers) values. I don't have time to experiment; I just changed things to use the quotes. It affects parsecss and flexcal; I haven't found any other places I used this.