matthew ephraim

Archive for the ‘javascript’ Category

It’s a (Firefox) bug!

Tuesday, September 30th, 2008

Sometimes it’s a relief when you find that a bug you’re trying to fix in your own code is actually related to someone else’s code. I’ve been trying to figure out why large text blocks inside of an xml file keep getting truncated when I read the file in with JavaScript. Turns out it’s Firefox Bug 452675.

Bug
FF 3 creates multiple #text nodes for elements with well under 
4096 characters of text data

Good to know I’m not crazy…

Keep tinyMCEPopup From Loading the Popup CSS File

Saturday, July 12th, 2008

This week I have been developing my first TinyMCE plugin. One of the first steps was designing the popup dialog box that would be associated with the plugin. Initially, everything was going smoothly. I had the XHTML and CSS just the way I wanted it and I was ready to move on to the next step of developing the JavaScript that would power the functionality of the plugin.

One of the utility files that TinyMCE allows you to include is a file called tiny_mce_popup.js. Including this file gives you access to a class called tinyMCEPopup. This class provides you with some helper functions that come in handy when developing the dialog box for a TinyMCE plugin. Unfortunately, including the helper file also has a side effect: the helper class will automatically include the current theme’s css file. In the case of my plugin, the css file for the current theme completely changed the way my plugin’s XHTML was styled. And not in a good way.

One solution would have been to modify my stylesheet or alter my XHTML so that the stylesheet didn’t interfere with the way I wanted the page to look. I tried to do this initially, but what I really wanted was for the theme stylesheet not to be included at all. As far as I can tell there’s no built in way to do force the tinyMCEPopup class to not include the stylesheet. So, I developed a workaround that seems to keep the stylesheet from loading without causing any side effects.

The first thing I needed to do was to unset the property that defined the theme stylesheet for popup dialogs. That way when the tinyMCEPopup class tried to include the file, it wouldn’t find anything to include. The location of the popup stylesheet is stored in the settings for the editor instance under editor.settings.popup_css. I figured out that the property could be unset at the beginning of the command that was executed when the button for my plugin was clicked.

JavaScript
editor.addCommand('mceMyPluginCommand', function() 
{		
	// Set the popup css to null while page loads 
	// because my plugin uses its own css
	editor.settings.popup_css = null; 
	...
});

This worked fine, but setting the popup_css property to null caused the stylesheet for any other plugin’s popup dialog to not load correctly. To get around this problem I needed to restore the original popup_css property once my plugin’s dialog box was finished loading. To do this, I simply added a command to the editor that would restore the original popup_css property.

JavaScript
// Registers an event that will 
// Add command to restore the original css file
ed.onInit.add(function() 
{ 
	var origCss = editor.settings.popup_css;
	editor.addCommand("mceMyPlugin_restoreCss", 
                       function() { editor.settings.popup_css = origCss; });
});

The previous two pieces of code could be run during the initialization of my plugin. Finally, I needed to use the tinyMCEPopup class inside of my popup dialog to call the function that restored the css.

JavaScript
// Restore the popup css to the original theme css
tinyMCEPopup.execCommand("mceMyPlugin_restoreCss");

It’s not the most elegant solution to the problem, but so far it’s the only way I’ve been able to figure out how to force the tinyMCEPopup class not to load the theme css file.

Be wary of JavaScript reserved words and globals

Monday, October 29th, 2007

If you’re writing some JavaScript and suddenly it stops working without any warnings or errors, make sure you’re not stepping on any reserved words or global objects. Tonight, I had a script that was working perfectly in Firefox, but as soon as I tested it in Safari it completely failed. It took me a little while to realize that I had named a property on an object “default”. Stupid mistake, but Firefox didn’t warn me about it and instead happily ran the script. I guess it goes to show that even standards compliant browsers don’t always behave the way you expect them to.

The Core JavaScript Reference is a good place to start if you’re looking for a list of keywords. Particularly the sections on Global Objects and Reserved Words. This list also wrapped many of them up nicely.

JavaScript Mouse Tracker

Saturday, October 20th, 2007

A while ago, I was thinking about software programs like Camtasia that allow you capture a user’s activity as they work on a computer. Screen capturing programs are useful for usability studies because they allow you play back a user’s activity later on when you are evaluating their performance on a set of tasks. I started to wonder if their were any options for capturing a user’s activity remotely through the browser. When I didn’t find anything I thought was compelling, I decided to try writing my own.

What I came up with was a JavaScript class I called MouseMovie that could be used to record the mouse movements a user made while on a page. The first draft is pretty rough, but it will allow you to create a new mouse tracker, start tracking the mouse movements a user makes on a page and then stop the tracker. Once data has been captured by the tacker, you can use the mouse timeline to replay the user’s movements or trace the path of the user’s movements.

JavaScript
/* Create a new tracker, 
start it and stop it and then use 
the timeline to animate 
and trace the mouse path. */
var MyTracker = new MouseMovie.Tracker(); 
MyTracker.start(); 
MyTracker.stop(); 
MouseMovie.Animate({TimeLine : MyTracker.TimeLine});
MouseMovie.Trace(MyTracker.TimeLine);

Currently, there is no way to persist the user’s movements to a file or database, but I’d like to make it possible to store the movements and play them back at another time. A simple demo of the mouse tracker can be found here