Posts Tagged ‘javascript’
Embedded Google maps
July 14th, 2010 at 11:52 pm
I’m my company’s default webmaster, and I spent a few hours today learning how to embed Google maps into our web pages. I figured I’d write up an example before I forget.
There’s a whole family of Google Maps APIs, covering JavaScript, Flash, static images, Google Earth images, and more. The JavaScript API makes the most sense for my website. I read through the tutorial and started modifying its simple example while consulting the developer’s guide and sections of the reference.
There are dozens of possibilities for creating an embedded map. I chose a fairly simple map with a custom marker and an info window. The result looks like this static image,

and is generated by this HTML/JavaScript/CSS melange:
1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3: <html>
4: <head>
5: <title>Embedded Google Map</title>
6: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7: <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
8: <script type="text/javascript">
9: function initialize() {
10: var drangLL = new google.maps.LatLng(41.74593, -88.17815);
11: var centerLL = new google.maps.LatLng(41.743, -88.18);
12: var myOptions = {
13: zoom: 15,
14: center: centerLL,
15: scrollwheel: false,
16: mapTypeId: google.maps.MapTypeId.HYBRID
17: };
18:
19: var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
20:
21: var contentString = '<span style="font-family: Helvetica, Arial;font-size: 80%">I\'m crossing this bridge in the<br />Springbrook Prairie Preserve.<br />Zoom in to see it.</span>';
22: var infoWindow = new google.maps.InfoWindow({
23: content: contentString });
24:
25: var marker = new google.maps.Marker({
26: position: drangLL,
27: map: map,
28: icon: "http://www.leancrew.com/all-this/images2010/littledrang.png",
29: title:"What am I doing?"});
30:
31: google.maps.event.addListener(marker, 'click', function(){infoWindow.open(map, marker);});
32: }
33:
34: </script>
35: <style type="text/css">
36: #map_canvas {
37: height: 500px;
38: width: 600px;
39: display: block;
40: margin-left: auto;
41: margin-right: auto;
42: }
43: </style>
44: </head>
45: <body onload="initialize()">
46: <p id="map_canvas"></p>
47: </body>
48: </html>
Line 7 imports the API, and Lines 8-31 use its methods to generate the map.
A variable for the position (latitude and longitude) of the marker is defined in Line 10, and one for the position of the initial center of the map is defined in Line 11. The options for the map itself, defined in Lines 12-17, set the initial zoom, center, and map type. I also decided to disable zooming with the scrollwheel, one of Google’s stupider ideas and a behavior that drives me crazy. It’s called a scrollwheel because it’s for scrolling. Google Maps is the only place I’ve seen a scrollwheel used for zooming.
The map is created in Line 19 using the options defined earlier. It’s placed in the item with ID map_canvas, which is the paragraph in Line 46.
The info window and its contents are defined in Lines 21 and 22. Pretty much self-explanatory, I think.
The custom marker is defined and added to the map in Lines 25-29. By default, the bottom center of the image is placed at the given position; this can be changed if there’s another point on your image that you want to be the “hot spot.” I didn’t bother.
Line 31 associates the info window with the marker and caused it to appear when the marker is clicked.
Lines 35-43 set up some simple CSS properties for the map.
Finally, the map code is invoked via the onLoad handler in the <body> tag on Line 45.
The result is a map with my head on the bike path in the Springbrook Prairie Preserve. You can do all the panning and zooming you’re used to in Google Maps. Clicking on my head pops up the info window.
The coding was pretty simple; the most time-consuming part was getting the latitude and longitude of the marker just right. If you zoom all the way in, you’ll see that my head is on a bridge over a small creek. To get it centered on the bridge I had to define the latitude and longitude in drangLL to 5 decimal points.
A new Twitter SSB
June 12th, 2010 at 9:13 pm
With the coming requirement to use OAuth to sign on to Twitter, I’ve had to abandon my Dr. Twoot client program and have shifted to a new Fluid-based SSB of the Twitter home page. I’m using a userscript to reformat the page and make it narrower.
Two reasons I couldn’t adapt Dr. Twoot to OAuth:
- I’ve read in several places, including in Twitter’s developer pages, that JavaScript isn’t appropriate for OAuth because it exposes certain tokens that are supposed to be secret. Dr. Twoot is written in JavaScript.
- As important, I just can’t find an OAuth tutorial that I understand. Everything I’ve seen is all about Consumers and Users and Providers and getting credentials from one site to use on another. I’m not interested in any of these two-cushion internet bank shots; I just want to log in to one site and use it.
So, barring a last-minute change in Twitter policy, Dr. Twoot will stop working at the end of the month. I’ve looked into other Twitter desktop clients, but haven’t found any I like. I’m dead set against installing Adobe Air on my computer, which cuts down the number of available applications considerably. I tried Tweetie, but for some reason it isn’t nearly as compelling on the desktop as it is/was on the iPhone. I liked the customization options of Kiwi, but didn’t like any of the themes that came with it. I didn’t want to buy an application and then spend a bunch of time programming just to get an acceptable look.
Which led me to Fluid. In a minute I had a new application—called, with a certain lack of imagination, Twitter—that was a site-specific browser for the Twitter home page. It didn’t have the look I wanted, but I eventually hammered out a userscript that gave me a nice narrow view of the timeline that I could keep over by the right edge of my screen.

The sidebar is still available by scrolling to the right.

As you can see, I made the tweet input area taller and added the IM Fell font for rendering @DrSamuelJohnson’s tweets. Less obvious, maybe, is that I’ve boosted the font size and the line spacing a bit to make all the tweets more readable.
I knew from my earlier Twitter userscript that the Twitter home page loads jQuery, which should have made the reformatting easy. Unfortunately, the layout of the Twitter home page is a mess. You’d think it would be clean and simple: there’s a background image, a header, a footer, and a two-column content area—not much more complex than this site, really. But the HTML of the Twitter home page is a nightmare of <div>s within <div>s. Some contents are allowed to spill out of their containers, others aren’t. The two columns that make up the main portion of the page comprise a one-row <table>, which has a very 1990s vibe.
My first experiments in narrowing the timeline were very frustrating. Everything I tried that should have worked didn’t. I started Googling to see if anyone had solved this problem before me.
As it happens, there’s a userscript called Endless Tweets by Mislav Marohnić that, among many other things, very cleverly reformats the Twitter page to a narrow layout when the user resizes the window to a small width. I didn’t want to use Endless Tweets itself—it had some minor rendering problems in my tests—but it gave me hope that I could get the timeline narrowed if I just kept at it.
Success eventually came when I opened the Twitter home page in CSSEdit, a seldom-used (by me, anyway) application that came with the MacHeist 2 bundle, and started playing around with the widths of various elements. I kept track of the tests that worked and incorporated them into my userscript. Here it is:
1: // ==UserScript==
2: // @name twitdrang
3: // @namespace http://fluidapp.com
4: // @description Makes Twitter narrower.
5: // @include *
6: // @author Dr. Drang (http://www.leancrew.com/all-this/
7: // ==/UserScript==
8:
9: function getIMFell() {
10: $("head link:last").after('<link href="http://fonts.googleapis.com/css?family=IM+Fell+English" rel="stylesheet" type="text/css">');
11: }
12:
13: function twitdrang() {
14: $("#container").css({'width':'600px'});
15: $("#header").css({'width':'600px'});
16: $("div#wrapper").css({'width':'400px'});
17: $("#side_base").css({'width':'200px'});
18: $("ol.statuses li").css({'width':'400px'});
19: $("fieldset.common-form").css({'width':'400px'});
20: $("#update_notifications").css({'width':'250px'});
21: $("ol.statuses span.status-body").css({'width':'300px'});
22: $("fieldset.common-form textarea").css({'width':'375px'});
23: $(".actions-hover li").css({'width':'20px'});
24: // $(".actions-hover .reply").css({'float':'right'});
25: // $(".actions-hover .retweet-link").css({'float':'right'});
26: $(".actions-hover .retweet-link a").css({'display':'none'});
27: $(".actions-hover .reply a").css({'display':'none'});
28: $(".actions-hover .retweet-link a").css({'display':'none'});
29: $(".actions-hover .del a").css({'display':'none'});
30: $("ol#timeline .status-content").css({"font-family": "Lucida Grande", "font-size": "15px", "line-height": "1.3"});
31: $("textarea#status").css({"line-height": "1.4", "height": "4.2em"});
32: $("li.u-DrSamuelJohnson span.entry-content").css({"font-family": "IM Fell English", "font-size": "120%"});
33: $("li.u-DrSamuelJohnson.latest-status span.entry-content").css({"font-family": "IM Fell English", "font-size": "175%"});
34: }
35:
36: if (window.fluid) {
37: getIMFell();
38: twitdrang();
39: }
40:
41: $(window).scroll( function() {
42: twitdrang();
43: });
If you’re interested in a narrow Twitter SSB, follow the Fluid instructions to make an application that points to http://twitter.com, and then add this to the Userscripts folder. I call it twitdrang.user.js, but you can name it whatever you want. If you’re reading this well after the day it was posted, you should look at the twitdrang GitHub repository because it’ll have the latest version.
You may find that any time you post a new tweet, or update the timeline by clicking the “xx new tweets” link, the new tweets will not be formatted to the narrower width. That’s because those events don’t trigger the userscript. I haven’t yet figured out how to get that to work, so in the meantime there’s a kluge. See Lines 41–43 in the code above? They cause the reformatting function to be run whenever the window is scrolled. So if you just wiggle the scrollbar after the new posts arrive, they’ll narrow themselves down just like the others.
Relative links in PNotes
May 31st, 2010 at 4:13 pm
In the last big change to my no-server wiki system—which I now call PNotes—I added the ability to categorize notes by subdirectory. This made PNotes more organized, but because I took some shortcuts in the programming I lost some of the portability of the system. In the last few days I’ve fixed the code to get portability back and uploaded the fixes to the PNotes GitHub repository.

One of my goals with PNotes was to create a wiki-like system that was self-contained within a folder—no reliance on a database system. I wanted to be able to move the PNotes folder anywhere—from place to place on my main computer, to my notebook, to someone else’s computer, to a CDROM or DVD, to my iPhone—and still have it work. When I added the ability to have notes in subdirectories, I decided to use a <base> tag in the <head> of each note to make it easier to generate the list of links in the sidebar.

The <base> tag made all the sidebar links absolute instead of relative, and this broke the portability I wanted. I could still move a PNotes folder anywhere on any of my computers because my computers have all the utility programs needed to regenerate the HTML files in their new location—all I had to do was reset the <base> and run make clean; make in the new directory. But I couldn’t zip up a copy of a PNotes folder and send it someone else, nor could I put it on my iPhone; the <base> would be wrong and screw up all the links.
Now, through a combination of Python and JavaScript, PNotes portability has been restored. You’ll need one line in the project.info file,
dirname = notes
to tell the system the name of the PNotes folder. I’ve always just used “notes,” but you can use any name as long as you set the dirname option accordingly. (I strongly suggest you stick to alphanumeric characters; the folder name is used in a regular expression, so special characters like parentheses and hyphens could mess things up)
Strictly speaking, the new PNotes isn’t perfectly portable. For example, the two “Edit” links in the sidebar won’t work unless the computer understands the txmt:// URL scheme for opening a file in TextMate (or BBEdit). And the contacts links won’t work unless it understands the addressbook:// scheme and has the same list of contacts with the same Address Book IDs. But all the links to notes should work on any computer.
The latest changes have made the GitHub README for PNotes a little out of date. I’ll be fixing it up in the next few days.
18th-century bookmarklet
May 24th, 2010 at 1:10 pm
Following up on this post, in which I tweaked my homemade Twitter client to display certain tweets in an old-fashioned font, I decided to create a JavaScript bookmarklet that would do the same when reading tweets in a regular web browser. This opens up 18-century rendering to everyone.
The bookmarklet uses JavaScript to show @DrSamuelJohnson’s tweets in the IM Fell English font, a webfont that Google has made available.

This should work in any browser. Just drag this link
into your bookmarks bar—you can change the name to whatever you like. If you follow @DrSamuelJohnson, clicking the bookmarklet when you’re at twitter.com will change the font of his posts. You don’t need to have IM Fell English on your computer; it’s downloaded as part of the page, just like a photo or screenshot.
You can, of course, read the bookmarklet to see how it works, but because it’s URL-encoded, there are lots of %22s and %20s in there that make reading hard. Here’s the unencoded source:
$("head link:last").after('<link href="http://fonts.googleapis.com/css?family=IM+Fell+English" rel="stylesheet" type="text/css">');
$("li.u-DrSamuelJohnson span.entry-content").css({"font-family": "IM Fell English", "font-size": "120%"});
Pretty simple. The first line sticks a link to the webfont into the <head> of the page. The second line grabs all the @DrSamuelJohnson tweets (list items assigned the u-DrSamuelJohnson class) and changes the font. Only the tweet text itself is changed; the meta information is left alone.
The bookmarklet uses jQuery, but there’s no need to link to the jQuery library, as Twitter already uses it.
It would be easy to extend the bookmarklet to change the fonts of anybody. If you follow me, please don’t change my tweets to Comic Sans; my feelings are easily hurt.
This isn’t the solution I really want, because the user has to click the bookmarklet. It would be better if the JavaScript were executed automatically after the page loads. That would probably require Greasemonkey (for Firefox) or GreaseKit (for Safari), neither of which I have any experience with. Maybe it’s time to look into them.
Update 5/24/10
Well, that wasn’t too hard—for Safari, anyway. Here’s a userscript for GreaseKit that does the font change automatically:
// ==UserScript==
// @name C18th
// @namespace http://www.leancrew.com
// @description Renders @DrSamuelJohnson's tweets in IM Fell English.
// @include *
// ==/UserScript==
$("head link:last").after('<link href="http://fonts.googleapis.com/css?family=IM+Fell+English" rel="stylesheet" type="text/css">');
$("li.u-DrSamuelJohnson span.entry-content").css({"font-family": "IM Fell English", "font-size": "120%"});
$("li.u-DrSamuelJohnson.latest-status span.entry-content").css({"font-family": "IM Fell English", "font-size": "175%"});
You’ll note that, in addition to the metadata at the top, I’ve added a third line of JavaScript. This line makes the text of @DrSamuelJohnson’s latest tweet appear in a larger font when I visit his Twitter page, as is conventional.
If you have GreaseKit installed for Safari, click this link to install and activate the userscript. I have it set up to work only with sites that have “twitter.com” in their URL.

This should work for Firefox/Greasemonkey, too, but it doesn’t. In fact, even the simple bookmarklet doesn’t work for me in Firefox. I don’t know why, and since I don’t use Firefox I don’t care enough to pursue it. If you know the answer, tell me in the comments or an email.
Division practice sheet
May 21st, 2010 at 11:26 pm
The school year is almost over, so here’s something your kids will love to play with over the summer: a division practice page that generates a new set of problems every time you refresh. Yippeee!

It’s set up like my other math practice sheets, a self-contained HTML file with all the JavaScript and CSS included. Use it from the web or download it to your computer—your browser will open it either way. Each time you open the page (or refresh it), you get a new bunch of problems. Print them out and give them to your grade-schoolers to practice with.
Every problem is a 4-digit number divided by a 2-digit number. The numerals are big and the space below each problem should be enough for the lines of long division. The problems do not necessarily have integer quotients; this is for kids who know about remainders.
Here’s the bad news: every browser will be able to open the file, but not all browsers will display it nicely. To get that nice curved line between the dividend (the big number) and the divisor (the small number) to meet the horizontal line above the dividend, I had to do some things with CSS that aren’t supported in older versions of Internet Explorer. So if you’re using a version older than IE 8, the problems won’t render correctly. You really shouldn’t be using those older versions of IE, anyway.
Worse, even the browsers that understand standard CSS render things a little differently with regard to character heights and page margins. To account for that, I’ve made three versions of the file:
- One for Safari (that’s the one I linked to above). This is the version I use and prints nicely on a single sheet of paper.
- One for Firefox. This renders the problems fine, but wants to print a second page that’s blank. Something to do with default print margins, I think. Just tell it to print only the first page.
- One for Chrome. Like Firefox, the problems look fine but the default page margins (or something) generate a second page that’s blank. Again, just tell it to print the first page only.
I believe that either the Chrome or Safari version will work with IE 8, but since I don’t have a Windows machine, I can’t test it.
If you can fix the printing problems with the non-Safari versions, I’d like to hear about it.
A small popup footnote change
May 7th, 2010 at 10:49 pm
Following up this post, where I described Lukas Mathis’s popup footnote jQuery script and my small adaptation to fit the look of this blog, I’ve made another small change you may be interested in. It removes the Daring Fireball-style return link from the end of the popup.
If you use PHP Markdown Extra, as I do, your footnotes will be followed by a little return arrow, ↩, that links you back to the main text. Michel Fortin, the author of PHP Markdown Extra, chose this style of return link to match that used by John Gruber on Daring Fireball. This is fine for footnotes at the end of a post, but makes no sense in a popup, because the popup doesn’t move you away from the main text.
In Mathis’s original implementation, the little arrow appeared in the popup, like this:

I’ve added one line to eliminate the unnecessary return link from the popup. Immediately after the newly created <div> is filled with the HTML contents of the footnote, I remove the return link:
div.html($(el).html());
div.find("a[rev='footnote']").remove();
The first line is there in Mathis’s original; the second is my addition. It finds, within the new <div>, the link with the rev="footnote" attribute and removes it. This removal applies only to the popup, not to the footnote at the end of the post.1
Not a big change, I’ll grant you, but it does look better. Obviously, if you want to do this and your footnotes use something else for the return link, you’ll have to use a different jQuery selector. But the principle is the same.
-
As you can see. ↩





