enableDrawing/enableEditing for GMap v3
Just a very quick message for now to say that I have been working on implementing a sorely needed feature in v3 of the GMap API. In v2, both GPolylines and GPolygons allowed the user to add to/modify the shape by calling the enableDrawing and enableEditing functions. This hasn't made it yet to v3, so I have gone and written my own. A demo can be found at: http://www.shanetomlinson.com/static/gmapV3EditablePolys/html/test.html.
It still needs a lot of work and right now only works with a Polyline, but I'll get there.
Right now it supports enableDrawing, enableEditing, disableEditing, you can refer to the GMap v2 API documentation to see the arguments these functions take.
The source has been uploaded to GitHub at http://github.com/stomlinson/Polyline-enableEditing-enableDrawing-for-GMaps-API-v3
Mile/Kilometer Markers for GMaps
This is an experiment to find mile and kilometer markers for any map type (even if there is no visual interface), but for now I have written a prototype to use the GMap v3 interface.
In the summers I like to run, up until recently I had always used the GMap Pedometer to log my runs. Last summer I started my own project to experiment with a lot of ideas floating in my head where I could log my own runs in an application that I wrote myself. One of the features I really like about the GMap Pedometer is that as you are creating your route, it shows distance markers at every kilometer or mile. This is something I wanted to do as well, and recently I got a chance to sit down an afternoon and write up the initial code. Over the last couple of nights I have written a generic class that can be used to find distance markers given any set of points that specifies a line and a GMap subclass that shows this in action using the GMaps API v3.
The biggest thing that took this mini project a long time to get started on is I didn't really know where to start with the math - I knew if I dug out some geometry books I could get the formulas together, but luckily I found out that somebody has already done the work for me and made a very nice Javascript library to do it. Chris Veness with his blog at http://www.movable-type.co.uk/ had just the formulas I needed to get this done. His very useful library can be found at: http://www.movable-type.co.uk/scripts/latlong.html
So here is the breakdown of my code and how you can use it.
There are right now two classes, one a generic class called DistanceMarkerPointsCalculator. Given a line represented by a series of LatLon's, it will calculate where distance markers should be along that line.. There are a few functions that the user of this class needs to know about. The first is addPoint. addPoint adds a LatLon (what Chris' class uses to perform geometric calculations) which represents a point on the line that you want the distance markers for. There is a second function loadLine that can be overridden if the user of this class is subclassing for a particular map type. loadLine takes what your internal representation of a line is and converts it to a series of LatLons. Each LatLon should be added to the class using addPoint. The third function the user of this class needs to know about is latLonToDistanceMarker. latLonToDistanceMarker can be overridden by the user of this class, its purpose is to take a LatLon which represents the point where a distance marker should be and converts it to something that the user can use. Once your line is loaded, the user then calls getDistanceMarkerPoints with the distance between markers - in kilometers. This function will call latLonToDistanceMarker, if it is overridden you can place your points on a map there, or if it is not overridden, getDistanceMarkerPoints will return an array of LatLons that can be used to plot the points.
What I have done is write a subclass of DistanceMarkerPointsCalculator called GMapsDistanceMarkers. The purpose of this class is to make DistanceMarkerPointsCalculator useful for v3 of the Google Maps API. It takes a Polyline, converts each LatLng to a LatLon, performs the calculation, and then in latLonToDistanceMarker, it adds a Marker onto the GMap being shown. This is only an example and can be modified to suit whatever needs you have, whether it be to do some non-visual calculations or whether it is to display points on a Microsoft or Yahoo based map.
This project is checked into GitHub at http://github.com/stomlinson/Distance-Markers. There is a working demonstration of the GMap subclass in action at: http://www.shanetomlinson.com/static/distanceMarkers/tests/gmapsDistanceMarkersTest.html
Converting arguments to a Javascript Array
Inside of any function, the Javascript variable arguments is available to the programmer to use. arguments is an array-like object, but the standard array operators like splice do not work without some conversion.
This is the snippet to convert:
... var args = Array.prototype.slice.call( arguments, 0 ); // use args here as a native Javascript array. ...
The reason I need this is that recently, I have had to create a sort of generic proxy pattern to interface with a Flash widget. The proxy calls Flash object functions only when the widget is ready. I am not fully convinced that the way I have implemented this is "good" and am wondering if there is a better way, if anyone has a suggestion, I'm open. To do the task, I had to convert the Javascript arguments object into a real array so that I could do some array manipulation.
My interface to the proxy is:
...
callFlashFunction: function() {
// The Flash function name to call.
var funcName = arguments[ 0 ];
// Convert arguments to an array.
var args = Array.prototype.slice.call( arguments, 0 );
// Remove funcName from the arguments list
args.splice( 0, 1 );
// Gets a reference to the flash object from an object member function.
var flashObject = this.getFlashObject();
// Finally do the call with the correct arguments list.
flashObject[ funcName ].apply( flashObject, args );
},
...
The first item (index 0) in the array is the name of the Flash function to call, all the subsequent items are parameters to pass to the Flash object. To pass the correct arguments list to the Flash function, I want to pass only items with indexes 1..N.
An example of calling this is:
calendarProxy.callFlashFunction( 'showWeek', 34, WeekDays.SUNDAY );
'showWeek' is the name of the Flash object function to call. 34 and WeekDays.SUNDAY are passed to showWeek as parameters.
So that is my use. If anybody has a suggestion on how I can improve this code, please let me know.
update April 27, 2010
Originally I used:
var args = [].splice.call( arguments, 0 );
But found that Internet Explorer would not support this.
Been a while
It's been a while, between returning to Tahoe to snowboard and my new job (still under wraps), I have felt too lazy to write anything, it's really quite sad. Time to get back to this. Today, a short snippet that I found today that I loved.
On Starting a New Job
This week, I started a new contract job with a different company (I'll say who when I can), while still working at Ubernote/KeepFu trying to get the final touches on a new product there, and this weekend leaving to go on vacation, the world is on fire, or at least my brain is. The opportunity with the new company is really good, it is a project I am interested in using the front-end skills I have learned over the past couple of years, there are some new technologies (to me) involved as well that I am looking at hoping I can learn someday, and the idea is something I believe in, when I first heard the description of it, the message resonated clearly with me.
But the mad dash this week, I have felt this way before, that feeling that comes when first starting a new job. Because it is new, I just want to solve it all, fix it all, make everything right, and now. My interest is held purely from the freshness of it, the new problems to solve, the wanting to create, create, and do it well. And the insecurity of wanting to get it all done NOW so as to make a good impression. After working both jobs yesterday I got up from the dinner table, my eyes red from staring at the monitor, Charlotte saying, "you have to blink sometime."
I had this before, I've had this several times before. Working hard is nothing new, working long hours is nothing new. But at the same time, like Charlotte said, "I have to blink sometime." Long hours are great sometimes, I can get a lot done, but I have to remember that at some point more hours does not mean more productivity, it means less. It means stupid mistakes. It means a fatigued brain. It means I miss out on all the other stuff there is still down the 17 stairs to the door out of the flat. I know I have a vacation coming up this weekend, but I can't be dead at the start. I have to remember to eat, to run, to take a bike ride, to take advantage of the remaining warm evenings, and to be with my girlfriend.
Observer/Listener Pattern in Javascript
At Ubernote, KeepFu, and my current exercise tracking side project, I write a lot of interactive software in Javascript that requires the use of the Observer pattern. An observer pattern real world example that everybody doing web development knows is the DOM Event system. What the observer allows you to do is register a callback function that is called whenever a particular event happens. This capability is invaluable whenever you are writing a system and the code that generates the event does not (and maybe should not) know about all the players that care about the event happening. The observer pattern promotes a separation of concerns and easy extensibility of systems.
This is the second one I have written, and it is a work in progress. Those familiar with jQuery's event system will find the syntax very familar. At the moment, it only allows for the binding and triggering of events, not unbinding. The reason this is so similar to jQuery's syntax is because I was experimenting one day and tried using the jQuery event system on non-DOM objects and to my surprise, it worked in Chrome, and Firefox 3.5, but in Firefox 3.0 I had a lot of 'infinite recursion' errors. I wanted to use the same syntax and didn't want to rewrite any of my in place code to do it. There are no shortage of Observers on the net, but many are pretty heavy weight, and none conform to jQuery's syntax, at least that I have found.
The current code can be found at http://shanetomlinson.com/static/observer/Message.js. An example showing the usage is at http://shanetomlinson.com/static/observer/listener_observer_example.html.
And now for the rundown. The code uses an entry function Message that you call on the object you want to bind listeners to.
To bind a listener to a message on an object:
Message( object ).bind( message_name, callback );
To trigger an event:
Message( object ).trigger( message_name, data );
Example:
var testObject = {};
Message( testObject ).bind( 'testmessage', function( event, value1, value2 )
{
alert( 'event: ' + event.message + ' value1: ' + value1 + ' value2: ' + value2 );
};
Message( testObject ).trigger( 'testmessage, [ 'testvalue1', 'testvalue2' ] );
The code:
/**
*
* Message - An observer/listener pattern for Javascript.
* Usage:
* To bind a listener to a message on an object:
* Message( object ).bind( message_name, callback );
* To trigger all listeners bound on a message on an object:
* Message( object ).trigger( message_name, data );
* When calling a callback, it will be called in the contxt of the
* object being registered upon. The input parameters will be:
* event, data1, data2, ..., dataN
* Example:
* var testObject = {};
* Message( testObject ).bind( 'testmessage', function( event, value1, value2 )
* {
* alert( 'event: ' + event.message + ' value1: ' + value1 + ' value2: ' + value2 );
* };
*
* Message( testObject ).trigger( 'testmessage, [ 'testvalue1', 'testvalue2' ] );
*/
Message = function( object )
{
if( !object.__objectID )
{ // Gives the object an ID if it doesn't already have one.
object.__objectID = ( Message.currID++ ).toString();
} // end if
// return an object that contains the functions that can be worked with.
return {
bind: function( message, callback )
{
var handlers = Message.messages[ message + object.__objectID ] = Message.messages[ message + object.__objectID ] || [];
handlers.push( callback );
return this;
},
trigger: function( message, data )
{
var handlers = Message.messages[ message + object.__objectID ];
if( handlers )
{
var event = {
target: object,
type: message
};
var callbackArgs = [ event ].concat( data || [] );
// go through all the handlers and call them with the arguments list we made up.
for( var index = 0, handler; handler = handlers[ index ]; ++index )
{
handler.apply( object, callbackArgs );
} // end for
} // end if
return this;
}
};
};
/**
* static variables used for the message processor.
*/
Message.messages = {};
Message.currID = 0;
A quick review of the code.
To make everything work, we have to keep a database of callback functions for every message/object pair. Javascript provides us with an Object which is a nice storage device we can use as a database. Since we may want multiple listeners for each message/object pair, we use an array to hold the list of callback functions. What this means - use a single object as a database, the keys in this object are message/object pairs. The values for each message/object pair is an array that holds a list of callback functions. To use a Javascript Object as a database the keys have to be text or numeric, this presents a problem because we are registering our listeners on objects, which are neither text nor numbers. To get around this, we give each object that is registered a unique text ID. We attach the ID as a property of the object named __objectID. With the object having a text ID, we can create message/objectID keys into the database.
Message is our accessor function which allows us to bind listeners and trigger events. Our database is stored as a static variable on the Message function. To ensure that we are also generating unique IDs for every object registered, Message also stores a static variable called currID. Note that we are storing the list of callbacks in an external object and not on the object itself. On the object itself, we store a text ID. The reason for this is that I want to be able to use this system to bind custom events to DOM elements, and I wanted to avoid IE memory leak involving circular references and DOM elements.
Whenever binding a listener to an object or triggering an event, we first look at the object to see if it has been assigned a unique ID. If not, generate one. When binding a listener, look in the database to see if a list of callbacks already exists for the given object/message pair. If not, create an array and store it in the database under the key/object ID pair. We then add the callback to the array.
Whenever triggering an event for an object, we look in the database to see if there is a callback list for the given object/message pair. If there is not, do nothing. If there are callbacks, we do a little bit of magic to make this a bit more similar to a jQuery events. First we create an event object that contains a type and the target. The type is the message that was triggered, the target is the object the event was registered on. Once we have that, we make an array out of the event, and each item in the 'data' argument that is given to the trigger function. We then iterate through each callback in the list, passing it the array we generated as its arguments.
Right now my biggest concern is that I am unsure of what the memory usage will be if registering thousands of callbacks. I make use of closures, which can eat up a fair amount of memory, so I will have to see what effect this has.
I plan on a lot of future improvements to this. Two of the more immediate needs are adding the ability to unbind a callback as well as adding the facility to trigger an event asynchronously. The asynchronous behavior will add an amount of overhead, but I have found with Ubernote that it can really help with the responsiveness of DOM events.
If you have any feedback/suggestions/ideas, please let me know. My email address is set117@yahoo.com
Reducing Initialization Flicker in tinyMCE
At Ubernote we have been using the tinyMCE editor for a long time. I've been happy to submit a few patches back to them, and this looks like another one that is going to go their way.
To change the default styling of the contents of your editor, tinyMCE has the ability to attach user defined stylesheets to the editor's <iframe> using the "content_css" option, and this takes care of most everything I need it to. Unfortunately, the loading of the CSS happens after a noticeable delay once the contents of the editor area already loaded. In our editor's CSS, we reset the margins and paddings to 0, as well as reduce the default font size to .8em. Most browsers have a default body padding of 10px, with a default font-size of 1em. Because of this, when tinyMCE first loads up, the contents within the editor's body are slightly indented and the contents of the editor are 1em. Once the stylesheet is downloaded and processed, the padding goes away, and the font size is reduced. This process, even on fast machines, is noticeable. On slow machines it is a second more more. Not exactly pretty behavior.
Normally when loading a web page, CSS files are attached in the <head> of the document. The CSS is downloaded and processed before the rest of the contents are displayed, and your document appears how you want it to. Unfortunately, tinyMCE has had to work around a lot of browser incompatibilities, because of this the author had to load up the contents of the editor's <iframe> and then after a slight delay attach the CSS, which is where this flicker comes from.
The question I asked myself in a complete "duh" moment was, "So why not attach a styling directly to the body before the CSS is loaded?" Elegant? From a purist standpoint, no, not really. Does it work? Yes. At least we can make things slightly more generic and make the styling we want to attach a configuration option.
This solution does require modification of the tinyMCE code, so make a backup of your tinyMCE directory before you start editing.
In the classes subdirectory, find Editor.js. Load it up.
In init, find the following line:
t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';
Replace it with:
var bs = s.body_style || '';
if (bs.indexOf('=') != -1) {
bs = t.getParam('body_style', '', 'hash');
bs = bs[t.id] || '';
}
t.iframeHTML += '</head><body style="' + bs + '" id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';
What we did here is simple. We are looking in the settings for an option called 'body_style'. Process it like the 'body_id' and 'body_class' before it. This extra processing is in case the parameter was given as a hash for multiple editors, find the body_style for this particular editor instance. Then, when we create the body for the IFRAME, we are setting the style to be the style we passed in in our body_style parameter.
To use this in your tinyMCE.init, you would add a line in your configuration such as:
// previous configuration items
body_style: 'padding: 0; margin:0; font-size: .8em;'
Notice the lack of flicker.
jQuery’s Missing Function, cancelEvent, part 2
Alright, a couple of posts ago, I wrote about jQuery's missing function, what I call cancelEvent. It is a combination of preventDefault() and stopPropagation(). I use it quite a bit at Ubernote for a whole slew of things, but have realized that my approach of editing the source works great, if you are serving the source up yourself. For those that are serving their jQuery from Google API, this does not work so well. We can't just ask Google to change jQuery for us, and since this is not a W3C function, the chances of it ever making it into jQuery are slim to none. So, we have to do it ourselves.
In the web page where you include Google API's jQuery via a direct call to the library:
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'></script>
<script type='text/javascript'>
jQuery.Event.prototype.cancelEvent = function(){
this.preventDefault(); this.stopPropagation();
};
</script>
I have not tested this with using the google.load("jquery", "1.3.2") method yet, this may not work depending on how Google creates the script element for jQuery. I'll let you know when I do test it.
Bridging a Wireless Card in KVM/QEMU
After two years of using VMWare Server under Linux to load up virtual machines to do development, I started to become frustrated with its poor disk IO performance. I have been growing impatient for a while, but last week finally decided to give KVM a try. I read some very good things about KVM's performance, especially on Intel or AMD chips that support virtualization. Setup was painless, I just apt-get'd the kvm package and everything was ready to go. The default network settings under KVM is to NAT a connection through the host's outgoing interface, giving the guest OS has access to the outside world. Unfortunately, if any machine needs to connect to the guest, under the default setup, there is no way to do this. I often start up a web server on my development guest and use other guest VMs to test how different browsers under different operating systems view what I am developing. This means I need to be able to access port 80 on the development virtual machine.
There are plenty of articles showing how to bridge an interface in KVM to give the functionality that I want, with a caveat that most wireless cards cannot do this. A huge problem on my laptop where I connect the LAN cable once per year. I found a post by bodhi.zazen that shows how to bridge a wireless card in KVM using a TUN/TAP device, just what I need.
The solution worked without flaw, but the approach meant that I needed to reserve an IP address on a network that is otherwise completely served by DHCP. Linux NAT to the rescue. My revised approach is to set up a TUN/TAP device, give the device an IP address, which under linux creates a route to that network, and we can easily access services on the virtual machine without polluting the external networks IP address space.
Follow the approach in bodhi.zazen's post until step 5.
Modified step 5:
Configuration. This step is a bit complex.
A : Network. Assume a network of 192.168.2.0/24 with a router (used for DNS) at 192.168.0.1 B : Ignore this, our step changes this in step C. C : Tap. We assign a ip address to the tap, it will become the default gateway for the guest. By setting up this IP address, linux will create a route to the guest's network. tap's IP address = 192.168.2.1 D: Guest. DHCP does not work so you will need to manually configure a static IP address of the guest. IP address = route we assign to the tap, in this example 192.168.2.2 Netmask = 255.255.255.0 Default gateway = 192.168.2.1 DNS (nameserver) = 192.168.0.1
With that background …
ip link set tap0 up ifconfig tap0 192.168.2.1
Start step 6 until:
Address = 192.168.0.20 <- From the route command.
Change this next section to:
Address = 192.168.2.2 <- From the route command. Netmask = 255.255.255.0 Gateway = 192.168.2.1 <- IP address of the host. In the DNS Servers box use 192.168.0.1 Click the "Apply" box.
Finally, follow his "extra credit" portion. That's it , it should be working.
jQuery Event’s missing function – cancelEvent
Well, it's not officially a missing function according to the W3C spec, but it is a function that I have found very useful over the past couple of years of DOM work. The missing useful function is, as I call it, cancelEvent. According to the level 2 spec, there are two main functions that can be called on an event (Level 3 has more), preventDefault and stopPropagation. preventDefault prevents the default action of the event, for the element the handler is registered on. stopPropagation keeps the event from propagating (bubbling). cancelEvent is a combination of the two, i.e.:
function cancelEvent( event ) {
event.preventDefault();
event.stopPropagation();
}
Where is this useful? Anywhere you want to prevent the default action from happening and you want to stop the event from bubbling.
DOH. My particular use has been buttons of all sorts where I do not want a link to open, nor do I want any click handlers further up the DOM being called.
My patch to jQuery (currently working off of version 1.6.3):
find the line:
isImmediatePropagationStopped: returnFalse
and overwrite that with:
isImmediatePropagationStopped: returnFalse,
cancelEvent: function(){
this.preventDefault(); this.stopPropagation();
}
To use in your event handlers that take the event as an input parameter:
function foo( event ) {
event.cancelEvent();
}
Simple.