jQuery-SVG UI

Recently I played a little with SVG, using the JavaScript library Raphael and later jQuery-SVG. I want to share some of my experiences with it. My test setup of browsers include:

Chrome 20.0.1132.57
Firefox 12.0
Opera 11.60

The idea I had, involved creating a user interface controlled by JavaScript. For the sake of this article I limit this to the following: Multiple windows constructed out of a border and background, a title bar and a ‘knob’ for resizing, that only appears on hovering. The user should be able to move the window by dragging the title bar and to resize the window by dragging the resize knob, both events should bring the window to the front.

Because I’d never done anything before with SVG, I used Raphael at first, a very easy to use API. In Raphael, I created a Set with the various elements: paths for the outline, title and resize knob. To move and resize the window I used the drag event provided by Raphael.

The problem with this, that I only later realized, is that Sets are just arrays to logically group elements together, they are not grouped within the SVG document. If you change a transformation on a Set, Raphael is manually updating all transformations on all elements within that Set, a potentially very expensive operation. This is how our window document would look like with Raphael:

<svg version="1.1">
  <path d="[window border path string]" transform="translate(100, 100)" />
  <path d="[window title path string]" transform="translate(100, 100)" />
  [...]
  <path d="[bottom right resize button]" transform="translate(100, 100)" />
  [...]
</svg>

Turns out SVG already supports real element grouping (d’oh) with the <G> element! That was the moment I ditched Raphael (even though there is an experimental plugin that uses <G> for sets, but who knows what else is done this inefficiently?). jQuery-SVG is a nice alternative that provides a more direct API for SVG manipulation.

The same document using this approach would look something like this:

<svg version="1.1">
  <g id="window_id" transform="translate(100, 100)">
    <path d="[window border path string]" class="outline" />
    <path d="[window title path string]" class="title" />
    [...]
    <path d="[bottom right resize button]" class="resize">
  </g>
</svg>

Another interesting SVG feature I explored was the <DEFS> and <USE> elements. Its possible to declare groups within <DEFS> and to instantiate it with a <USE> later on, <USE> provides X and Y attributes so you don’t even need to transform/translate anything! That sounded really great in theory, but then the browser bugs started coming in:
Firefox has an 8 year old bug that prevents any events of elements within <DEFS> to be propagated (and a related bug: .getBBox() is also broken). Chrome and Opera work great until you discover their inability to show :hover effects correctly. At the end and after a lot of wasted time on (not so) possible workarounds, I decided to forget about <DEFS> and <USE> completely.

To theme the window you can use a stylesheet like this:

.outline, .title {
    fill: white;
    stroke: black;
}
.title:hover {
    fill: black;
}
.resize {
    fill: none;
    pointer-events: all; /* otherwise no mousemove event would be propagated */
}
.resize:hover {
    fill: black;
}

Now to create the window, I first created functions that return the paths based on the current dimensions of the window (you could also use translate in some cases, has that an impact on performance? Idk):

function outlinePath(width, height) {
    return [
        'm', 0.5, 0.5,
        'h', width,
        'v', height - 10,
        'l', -10, 10,
        'h', -width,
        'v', -(height-10),
        'l', 10, -10,
        'z'].join(' ');
    }
function titlePath(width) {
    return [
        'm', 5.5, 5.5,
        'h', width-10,
        'v', 10,
        'l', -10, 10,
        'h', -(width-10),
        'v', -10,
        'l', 10, -10,
        'z'
    ].join(' ');
}
function resizePath(width, height) {
    return [
        'm', width + 1.5, height - 10 + 1.5,
        'v', 10,
        'h', -10,
        'z'
    ].join(' ');
}

and to create the svg structure procedurally:

var x = 50, y = 50, width = 100, height = 100;
var g = svg.group({id: 'window_id'}); 
function moveWindow(x, y) {
    svg.change(g, {transform: 'translate('+x+','+y+')'});
}
var outline = svg.path(g, outlinePath(width, height), {class_:'outline'});
var title = svg.path(g, titlePath(width), {class_:'title'});
var resize = svg.path(g, resizePath(width, height), {class_:'resize'});
moveWindow(x, y);

first lets allow to move the window by dragging the title:

var lastDragX, lastDragY;
var mousemove = function (event) {
    moveWindow(event.clientX - lastDragX, event.clientY - lastDragY);
    lastDragX = event.clientX;
    lastDragY = event.clientY;
}.bind(this);
var mouseup = function (event) {
    $(window).unbind('mousemove', mousemove);
    $(window).unbind('mouseup', mouseup);
}.bind(this);
$(title).mousedown(function (event) {
    lastDragX = event.clientX;
    lastDragY = event.clientY;
    $(window).bind('mousemove', mousemove);
    $(window).bind('mouseup', mouseup);
    event.preventDefault();
}.bind(this));

almost the same for resize, just instead of moving the window:

width += event.clientX - lastDragX;
height += event.clientY - lastDragY;
svg.change(outline, {d: outlinePath(width, height)});
svg.change(title, {d: titlePath(width)});
svg.change(resize, {d: resizePath(width, height)});

To bring a window to the front you can just do this:

svg.root().appendChild(group);

You can look at a demo here.

This looks really easy now, but it took me a while to get to this point. I recommend anyone who wants to do something serious with SVG, to look at the specs and to use a low level API, also make sure to look at different browsers to see what bugs they throw at you.

Feedability: Node.js Feed Proxy With Readability

This is something I’ve planned to do for a long time, so I’m really happy that finally I was able to do it.

There is a common (annoying) habit of commercial news sites, to publish only short article excerpts (if at all) in their Feeds. Although I can totally understand why they do this (to increase page impressions/ad revenue), it really distracts when you read with a feed reader and need to open a web browser everytime you want to read the complete article, this gets even worse in situations where you’ve no Internet connection available. Another possible scenario is when you’ve waited too long and the article is already been unpublicized, and yes the german public broadcasting stations are actually forced (by the German publisher lobby) to “unpublish” (“depublizieren“) their content after some days. These are (for me at least), totally valid points that justify the effort to do something against it.

It is of course not a new problem, as I said I’ve planned to do something for quite some time now. One of the first solutions I came up with was to use specified regular expressions to extract the content of articles and built a new feed (including the extracted full article text). I’m not the only one who thought of this solution, there are for an example some Snownews/Liferea/Newsbeuter filter scripts available that do exactly that. This works, but it would be better to have a more generic solution besides specifying and maintaining regular expressions (or XPath for that matter) for all the news sites and (“commercial”-)blogs I read.

A more powerful approach to extract the articles, would be to use content extraction or template detection algorithms. I’d written an article (in German) about that when I played with some of these algorithms a while back. But I couldn’t find a suitable implementation, that was developed and stable enough to do this and I wasn’t really crazy about writing one of my own either.

Then in 2009 comes arc90‘s Readability that implements a mature content extraction algorithm in Client JavaScript. It is not perfect but I guess it is by far the best open source solution available for it right now. One problem in particular that I’ve noticed are comment sections below articles, sometimes comments include more text than the actual article, this can confuse Readability to think that the comment is the actual main content. So although it works most of the time, you should expect problems like this. The first application that I’m aware of using Readability for feeds is the Apple feed reader “Reeder” that can fetch the full text for selected articles.

There are some approaches to port Readability to other languages, but I’ve never seen a complete reimplementation. A few days ago I stumbled upon a Readability node.js library written by Arrix Zhou that uses just a slightly modified version of the original. Since I’ve planned to learn node.js anyways (like most people I’ve only written client JavaScript before) I used the opportunity to write Feedability:

Feedability is written in javascript using the v8 engine and node.js, it requires the node-readability and node-expat libraries that can be installed using npm. Feedability implements a small HTTP Server, you sent the feed you want to read just as a query string, so for instance: http://127.0.0.1:1912/http://example.com/atom.xml The node.js server will download the feed and parse it for item links (article links), it will also remove any existing content excerpts. Then it crawls all articles and uses readability to extract the content of the received pages. The original feed will be extended with the full-text of the articles and send to the user (the feed reader software). Feedability also supports filters based on jquery selectors.

I’ve tested it with Atom, RSS1.0 and RSS2.0 Feeds, but there are some known bugs, for instance: The character encoding breaks sometimes. As I said this is my first Node.js application, there are some parts that I’m particular unhappy with, for example the current feed parser/generator based on expat (lib/feed.js), maybe I’m going to rewrite that sometime.

Live Transcoding for Video and Audio Streaming

With slowly increasing upload bandwidths (even in Germany), video and audio streaming for home servers become feasible. In Germany, currently the highest upload bandwidth you can get as a non-corporate is 10 Mbit/s with VDSL, enough to provide actual viewable video streaming in near DVD quality to a small number of concurrent viewers. However it was kind of hard to get a setup working that suits my requirements.

In my case the starting point are video and audio files, the video files are mostly XviD (MPEG4) encoded (with one or multiple MP3 or AC3 audio streams) in AVI containers. The audio files are mostly MP3 files with a constant or variable bitrate.

Because I want to stream (more or less) directly to the browser, possible player technologies are: Browser Plugins (WMP/ActiveX, Mplayer/VLC Mozilla Plugins, Quicktime), Flash or HTML5 Video and Audio Tags.

All of them support different codecs, containers and streaming protocols. I use HTTP as a streaming protocol for a numerous of reasons, but lets just say the decisive factors are that HTTP is supported by all mentioned players and is easy to integrate in existing web applications.

Browser Plugins

The different player plugins are a mess, there is no standard what so ever and it is hard to make any cross platform assumption on support of this. It has the theoretical capability to stream my video and audio file formats but in my experience it is most likely to fail out of the box so I would not count on that.

Flash

The popular flash plugin supports the mediocre Sorenson Spark and VP6 video codecs and most recently H.264 video. The audio codecs are MP3 and most recently AAC. Flash uses its own Container Format FLV, in more recent versions other containers are also supported.

There are two notable non-free open source flash players. The jwplayer (custom commercial/open source license) with a phone home logo/branding and flowplayer with a (In my mind) violating GPLv3 dual license and branding.

Maybe I should mention that Flash supports their own proprietary streaming protocol RTMP, since its DRM infected (RTMPe) and just evil, I ignore it, even through there is an open source server implementation.

The major problem of flash video is (besides of its proprietary status) the exceedingly modest video decoder that requires high end hardware and obscene resources to play even medium quality video.

HTML5

Most recent and upcoming browsers implement the Video and Audio functionality of HTML5. Unfortunately and due to the nature of HTML5, w3c does not specify video and audio codec requirements. As a result every browser and even different versions have a different subset of supported codecs. The formats are (Video Codec/Audio Codec/Container): Theora/Vorbis/OGG, H.264/AAC/MP4 and VP8/Vorbis/WebM. For more information visit the excellent site diveintohtml5.org.

Transcoding

Form to create streams with advanced settings.

I want support for HTML5 and Flash for my home server streaming setup, this should support streaming for all modern browsers and operating systems (even mobile devices). As you may have noticed, none of them can handle my commonly used file format and the variety of formats used for HTML5 makes transcoding unavoidable.

Transcoding means the encoding from one digital video/audio file to another. So the solution would be to transcode all files to the required formats (at least Sorenson Spark, H264 and OGV) beforehand. And now comes the tricky part: Because for some reasons (too many files, no disk space to waste) this is not an option in my case. Now normally that would be the end of this article, but I came up with a solution although it has its own problems and limitations.

Live Transcoding

The basic idea is to start the transcoding process the same time the user requests streaming for a audio/video file. It works kind of like a live feed, but instead of using the video and audio stream from a camera and microphone, it reads video and audio files. Because it starts a resource hungry encoding process for each stream, the maximum possible concurrent viewers are very limited. In my case, because my upload bandwidth is limited anyway, this is not really a problem, but in other, larger setups, it sure is.

Another big limitation is seeking, although theoretically possible with pseudo HTTP streaming, it is very difficult to implement in this kind of live streaming. I have some vague ideas how this could work, but I’ve not implemented any of it. As a kind of workaround, the user can specify a timecode, FFmpeg should seek to, before the transcoding starts.

One last thing: I talked about the different formats supported by HTML5 capable browsers. Some of them only support H.264/AAC within MP4 container. The problem is that, the MP4 container is not capable of streaming this way because it needs to seek inside the output file. FFmpeg will just quit with the message muxer does not support non seekable output. Theres a alternative for Apple stuff but I do not plan to implement that anytime soon.

Proof of Concept

I’ve created a proof of concept implementation using PHP, FFmpeg for transcoding and MPlayer to identify encodings and bitrates. The user can select player technology, audio/video bitrate (to transcode for lower bandwidths) and adjust the transcoding settings in detail. My solution is pointed to technical experienced users, depending on your audience you probably would use browser sniffing to hide technical details completely. The scripts need Linux, PHP5 and the Smarty Template Language installed. If you want to give it a try I’ve created a github repository: php-live-transcode. Make sure you met the requirements and change the config.inc.php file to match your setup.

Conclusion

I’m well aware about the different problems of this peace of software, although some could be fixed, there are some fundamental problems that are just unavoidable, so it is important that you are aware of the limitations before you use any of this. Notice the configuration value FFMPEG_MAX_INSTANCES, this defines how many ffmpeg instances should be allowed to run simultaneously, this is very important because this setup just calls out for a Denial of Service attack, so be careful.

I guess thats it for now, please leave a comment if you have tried it. Please use the issue tracker at github if you encounter a problem.

Memory Debugging or a “Universal Game Trainer” with Python and ptrace

Reading and writing other process memory can have many different purposes: besides debugging, this technique is probably most frequently known to be used by game trainers, to alter different values of a running game (like the value of health or money).

Most (if not all) of the game trainers available, are developed for Windows and only for a specific game, but there are some universal trainers, that could be used to locate and change values in memory of any game or application and with kcheat and Tursiops there are some solutions for Linux.
I’ve developed a proof of concept to locate and change any byte value using python and the ptrace bindings. ptrace is a Unix system call for controlling other processes, it is for instance used by the gdb debugger.

The following code creates a debugging instance and attaches the other process by PID:

from ptrace.debugger.debugger import PtraceDebugger
 
dbg = PtraceDebugger()
process = dbg.addProcess(1234, False)

Now the process instance can be used to inspect and manipulate the process. To manipulate the memory it is important to know the virtual memory mappings (‘areas’) of the process:

from ptrace.debugger.memory_mapping import readProcessMappings
 
memory_mapping = readProcessMappings(process)

Now the list contains MemoryMapping instances, describing the virtual memory areas of the process. We are interested in their location and permission (Quickref: mapping.start, mapping.end, mapping.permissions). The trainer should only be searching within memory mappings with “rw” permissions.

Last but not least, the reading and writing from/to memory methods:

value = process.readBytes(0x11223344, 1) # this reads 1 byte
process.writeBytes(0x11223344, value) # writes len(value) bytes

After that you can close the debugger instance by:

dbg.quit()

I encountered some difficulties with closing/detaching the debugging process, it seems that the process is only really detached if the script is terminated, as a workaround I forked the memory search process, to circumvent that in my proof of concept trainer.

That’s it! If you’re interested, you can checkout my proof of concept for a universal game trainer: pycheat.py (GPLv3) It can locate and change byte values (char) in other processes memory:

% python pycheat.py 8169
pycheat: universal game trainer v0.1
process id: 8169
highest address: 0xffffff
 
searching for address by byte value: 23
search memory area[0x00DB8000-0x00DC0000] address[0x00DBD989] value[0x17 (023)]    
 
found 5926 occurrences, change value to: 33
search memory area[0x00DB8000-0x00DC0000] address[0x00DBFD88] value[0x21 (033)]    
 
found 1 occurrence! correct address for this value is 0x00C4335A
change value in memory at 0x00C4335A to: 99
done.

First you enter the known value, the trainer is searching it inside the memory, chances are high, that there are many occurrences of it, so you change the value inside the game and repeat the search with the new one. After ~2-4 iterations the correct location should be found and you can manipulate it.

edit: smaller changes

Dynamic Loading of SDL

If you want to use the SDL library (or any other library for that matter) in your programs, you normally would just link with the library, for instance by -lSDL (GCC). Sometimes however, it would be more flexible to dynamically load the library at runtime. With dynamic loading, if your application supports alternative libraries (e.g.: GLUT SFML as an replacement for SDL), it can discover and use available libraries at runtime. The system your program is running on, just needs one of those libraries installed and can switch them without the need to recompile your program. This technique is probably most commonly used to load plugins into programs at runtime.

Theres a helpful Wikipedia article about Dynamic loading, they even describe how to load the SDL library in their examples. Besides that, theres an old discussion about that at lists.libsdl.org and an article at eaten by a grue (when good libraries go bad). However I didn’t find a complete example implementation for this, so I’m trying to create one with this article, although I’m not a very experienced C++ programmer.

The first thing to do is to load the library file, on POSIX/UNIX systems we do this with dlopen(), on windows we use LoadLibrary() and for closing dlclose() and FreeLibrary() respectively. The following code snippet for open/closing the library should work on both Linux and Windows systems:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifdef _WIN32
    #include <windows.h>
#else
    #include <dlfcn.h>
#endif
 
// [...]
 
#ifdef _WIN32
    HMODULE libhandle;
    libhandle = LoadLibrary("SDL.dll");
#else
    void *libhandle;
    libhandle = dlopen("libSDL.so", RTLD_LAZY);
#endif
 
// ... dlsym() and GetProcAddress() calls ...
 
#ifdef _WIN32
    FreeLibrary(libhandle);
#else
    dlclose(libhandle);
#endif

You need to link your programs to the dl library for this to work (such as -ldl in gcc).

The returned handle can be used to retrieve symbol addresses and then to convert them to function pointers. Theres dlsym() on POSIX and GetProcAddress() on Windows machines. The following code does that cross-platform for SDL_SetVideoMode():

1
2
3
4
5
6
7
8
SDL_Surface * (*p_SDL_SetVideoMode)(int, int, int, Uint32);
#ifdef _WIN32
    p_SDL_SetVideoMode = 
        (SDL_Surface * (*)(int, int, int, Uint32)) GetProcAddress(libhandle, "SDL_SetVideoMode");
#else
    p_SDL_SetVideoMode = 
        (SDL_Surface * (*)(int, int, int, Uint32)) dlsym(libhandle, "SDL_SetVideoMode");
#endif

You need to look at the header files (/usr/include/SDL/SDL_video.h) for the exact declaration (return and parameter types).

Theres a problem here, when casting from an void pointer that is returned by dlsym() to a function pointer which is prohibited by the C/C++ ISO standards. I’m using a simple explicit (C-style) cast here and in practice, I not even encountered a warning with modern compilers.

Johan Petersson has written an article (When standards collide: the problem with dlsym) about that problem in Scatter/Gather thoughts, I want to quote:

You probably noticed that I omitted the C-style cast from my earlier example. Alas, most C and C++ compilers will allow the conversion when you use a C-style cast. You may not even get a warning, even though it’s prohibited in ISO C as well as ISO C++. This kind of conversion is a common compiler extension. So common, in fact, that many people don’t realize it’s not in the standards.

The article is from 2004, I don’t know if the current C/C++ standards had changed any of that.

In the last code snippet theres an redundancy that can be resolved by using a typedef instead:

1
2
3
4
5
6
7
typedef SDL_Surface * (*Type_SDL_SetVideoMode)(int, int, int, Uint32);
Type_SDL_SetVideoMode p_SDL_SetVideoMode;
#ifdef _WIN32
    p_SDL_SetVideoMode = (Type_SDL_SetVideoMode) GetProcAddress(libhandle, "SDL_SetVideoMode");
#else
    p_SDL_SetVideoMode = (Type_SDL_SetVideoMode) dlsym(libhandle, "SDL_SetVideoMode");
#endif

Thats everything you need to call that function: (p_SDL_SetVideoMode)(...); The major problem here is that SDL has over 200 functions that “must” be declared and addressed this way. I’ve written a ruby script for Linux that does that for the SDL headers within /usr/include/SDL, at first it reads the symbol names directly from the libSDL.so shared library utilizing nm, then it parses the header files for the function declarations found by nm and generates the code for the pointer declaration and explicit casts (/dlsym calls) automatically.

I’ve created some example code that defines an abstract class DLLoader and an implementation DLLoaderSDL that includes an struct with the automatically generated function pointers etc. The test program loads the library and shows a SDL window for 3 seconds.
I’ve tested the program with GCC 4.5.0 (Linux), GCC 3.4.5 (Windows MinGW) and CL 14.0 (Windows VC++). I also added Makefiles for each of those compiler suites.

Update: I’m currently working on a new project that involves this dynamic loading and I’ve created a much more improved and flexible ruby script for parsing header files and built dynamic loader scripts:

Usage: src/dlib/dlib_generator.rb [OPTIONS]
Parse shared library binary and headers to generate code for a dynamic loader.

You need at least specify a name, a header file (or directory) and a prototype
pattern. The binary options are optional, but can help to improve the result.

Generator Options:
    -n, --name NAME                  The name used to identify the library
    -t, --template FILE              Use FILE as generator template 
                                     (Default: dlib_generator.tpl)
    -c, --config FILE                Use FILE for configuration, overwrites other options
    -w, --write [FILE]               Write generated code to FILE, in addition to stdout
                                     (Default file: CLibraryLoader#{options.name}.hpp)
                                     Need to be specified after name!
    -d, --define                     Create a C macro for each procedure
    -i, --include a.hpp,b.hpp        List include header files.

Library Header Options:
    -f, --header_file FILE           Use FILE or PATH for header declarations
    -p, --header_path PATH
    -r, --file_pattern PATTERN       Parse only files in header PATH that matches
                                     PATTERN (Default: \.h$)
    -R, --prototype_pattern PATTERN  Use PATTERN to parse procedures, assumes three
                                     groups: Return, procedure name and arguments

Library Binary Options:
    -l, --library FILE               Shared library FILE parsed with nm for symbols
    -s, --symbol_prefix PREFIX       Use symbol PREFIX to extract procedure names
                                     from shared library

Miscellaneous:
    -v, --verbose                    Activates console messages
    -h, --help                       Show this message

JavaScript: onMouseMove Google Translation

I wanted to implement a JavaScript onMouseMove Event, that translates the word under the mouse pointer with the Google Translator. I want to share the following solution.

I split this into the following two separate problems:

First: Detect word for an onMouseMove Event

The onMouseMove Event can listen on any Element for mouse movements. To detect the word under the mouse pointers position, I utilize the W3C(DOM-2) specified Range Object.

Most modern browsers support the Range object, but the event.rangeParent Attribute seems to be only supported by Firefox. Currently I’ve no cross-browser solution for this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
 * Apply offset to range and extract a single character at position.
 *
 * range -- the range object effected
 * originalOffsetStart, originalOffsetEnd -- Start offsetStart and offsetEnd
 * offset -- the relative offset to apply
 */
function getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, offset) {
    var character = ' ';
    try {
        range.setStart(range.startContainer, originalOffsetStart + offset);
        range.setEnd(range.startContainer, originalOffsetEnd + offset);
        character = range.toString()[0];
        range.setStart(range.startContainer, originalOffsetStart - offset);
        range.setEnd(range.startContainer, originalOffsetEnd - offset);
    } catch (e) {}    
 
    return character;
}
 
/**
 * Returns a single word for the given event.
 */
function getEventWord(evt) {
    if (!evt.rangeParent || !document.createRange) {
        return '';
    }
 
    var range = document.createRange();
 
    range.setStart(evt.rangeParent, evt.rangeOffset);
    range.setEnd(evt.rangeParent, evt.rangeOffset);
 
    // the word ends when this characters appears
    var stop_character_pattern = /^[\W]$/m;
 
    // this "overwrites" some characters from the above pattern
    var ignore_stop_character_pattern = /^['|\-]$/;
 
    // I assume startOffset == endOffset so set 1 character selection ...
    var originalOffsetStart = range.startOffset;
    var originalOffsetEnd = range.startOffset + 1;
    try {
        // test:
        range.setStart(range.startContainer, originalOffsetStart);
        range.setEnd(range.startContainer, originalOffsetEnd);
    } catch (e) {
        // out of bounds
        originalOffsetStart -= 1;
        originalOffsetEnd -= 1;
        range.setStart(range.startContainer, originalOffsetStart);
        range.setEnd(range.startContainer, originalOffsetEnd);
    }
 
    // First Step: Find left end of word:
    var leftCharacterPos = 0;
    var iChar = '';
    for (var iOffStart = 0; iOffStart <= originalOffsetStart; iOffStart++) {
        iChar = getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, -1 * iOffStart);
 
        leftCharacterPos = iOffStart;
 
        if (stop_character_pattern.test(iChar) && !ignore_stop_character_pattern.test(iChar)) {
            // remove the stop character!
            leftCharacterPos -= 1;
            break;
        }
    } leftCharacterPos = originalOffsetStart - leftCharacterPos;
 
    // Last Step: Find right end of word:
    var rightCharacterPos = 0;
    for (iOffStart = 0; true; iOffStart++) {
        iChar = getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, iOffStart);
 
        if (stop_character_pattern.test(iChar) && !ignore_stop_character_pattern.test(iChar)) {
            rightCharacterPos = iOffStart - 1;
            break;
        }
    } rightCharacterPos = originalOffsetEnd + rightCharacterPos;
 
    try {
        range.setStart(range.startContainer, leftCharacterPos);
        range.setEnd(range.startContainer, rightCharacterPos);
    } catch (e1) {
        range.detach();
        return '';
    }
 
    var retWord = range.toString();
 
    range.detach();
 
    return retWord;
}

Second: Translate Text with Google Translator

This is very easy because Google provides an very easy to use Ajax API for this (attend the possible google user tracking!):

1
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// read onMoveTranslate()
var last_word = null;
var timeout = null;
var word_cache = [];
 
/**
 * Translate text For onmousemove events.
 */
function onMoveTranslate(event) {
    // get element the translation should appear in:
    var translation = document.getElementById('translation');
 
    var word = getEventWord(event);
    if (!word || word == '') {
        return;
    }
 
    if (typeof(word_cache[word]) !== 'undefined') {
        translation.innerHTML = word_cache[word]; //+" (cached)";
        return;
    }
 
    if (word != last_word) {
        if (timeout) {
            window.clearTimeout(timeout);
        }
 
        translation.innerHTML = 'Translating ... ' + word;
        timeout = window.setTimeout(function(){
            google.language.translate(word, 'en', 'de', function(result) {
                if (!result.error) {
                    translation.innerHTML = result.translation;
                    word_cache[word] = result.translation;
                }
            });
        }, 800);
    }
    last_word = word;
}
 
google.load("language", "1");

At last I assign the onMouseMove Event to the onMoveTranslate() function:

1
<div id="content" onmousemove="onMoveTranslate(event);">

Here is an full Example for this.