Stanford University Wiki

Apture interface for adding links

229pages on
this wiki
Add New Page
Talk0 Share

Apture AnalysisEdit

Jing Chen and Benjamin Bercovitz


Apture is a service that allows you to add popup links to your blog or webpage, which can link to previews of other webpages, images, or videos. Once you register your blog on their site, you are given a piece of javascript to add to your blog. Then, you can add links to your blog by highlighting text while in editor mode (which requires signing in to apture). These links are displayed to other users viewing the site. We analyzed the process by which links are created using Apture.

Interaction StructureEdit

You can create a link by either highlighting the text that you want to link or by clicking on a divider that appears between paragraphs. This opens up a popup where you can specify what the link should be. This info is sent to the server, and the page is updated to show the newly created link. All other visitors will then see this link and hovering over it will give a popup of the page, image, or video.

In the sections below, we analyze how each step of the interaction is implemented, with a summary of the overall interaction at the very end.

Adding JavascriptEdit

Since Apture does not have direct control over the HTML sent to the browser, it must use Javascript to change the behavior. It does so by asking the user to add a small Javascript include to their page. In my case, the script sourced:

This script then adds children to the DOM of the page that pull in four Javascript files from the Apture server.

These Javascript files are the same for all blogs using Apture. They manage the interactions for creating and displaying links. Core.js handles the basic initialization, monolithic.js contains many common functions, editor.js handles many of the editor interactions, and linker.js handles the popup for creating links.

Selecting TextEdit

1. Highlighting textEdit

Highlighting text causes a linker iframe to be displayed at a location below the text. The linker component connects to many sources that might contain related media, like youTube and Wikipedia and displays top search results for each. The user can then select the related media to show when other users hover above the selected text (which has now been turned into a link).

When the apture global object is initialized in monolithic.js, a listener is added for the 'mouseup' event at the highest level using document.addEvent(). This listener closes any current linker iframes currently present, and calls userMadeSelection if the user is in edit mode.

The function userMadeSelection defines a local variable, $10, that differs in class depending on which browser is used, since they use different methods for giving the current selection. It can either use W3Selection for the Mozilla window.getSelection() or IESelection for IE's document.selection. Both of these classes inherit from the abstract class CanonicalSelection.

CanonicalSelection provides the functionality for getting information about the highlighted text. In particular, highlight() is interesting because it maintains the illusion to the user that the element is hightlighted by the cursor even after it loses its real position due to the linker popup opening. It does this by applying a CSS style to it that mimicks the real highlighting's look and feel.

One limitation is that a link cannot be created across the contents of sibling tags (for obvious reasons). This is handled by CanonicalSelection's isSingleTextNode method, which simply compares the DOM nodes for the start and the end of selection.

One interesting implementation innovation comes from this line in userMadeSelection(event, selection):

return $1O&&setTimeout(function(){apture.userMadeSelection($1N,$1O);},10);

Since this function is being called from an event dispatcher, it should not do expensive work (like searching through element text) after changing the DOM state because the browser may not render the page again until the event returns. The event handler already dismissed the previous linker window, so this lets the change be rendered more quickly. This setTimeout() hack lets the caller return immediately and then reenter the function 10ms later from the timeout dispatcher. Thus this function is specially written to maintain a snappy user interface. For more on this subject see Joseph Smarr's 2007 talk.

2. Selecting Between ParagraphsEdit

In editor.js, a class is defined called BetweenPassageControl, which sets the initial appearance of the divider, and its animation. Upon loading the editor, the divider is inserted between all passages by the function _cd().

The BetweenPassageControl is shown and hidden by controlling the opacity property using Javascript mouse events. Clicking is managed by binding a function, _cs, to the 'click' event. If it finds valid information about the location, then _cs() adds a placeholder (a square with dotted borders, with the text "Embed Media" in the middle) in place of the BetweenPassageControl.

_cy animates the Embed Media placeholder into place. onComplete for _cy is bound to _cz, which opens the linker popup (using getLinkerPopup()) as soon as the placeholder animation is done. The opening animation is performed by animateOpen(), from monolithic.js. The popup itself is created in monolithic.js, and used in several places, but the title and contents change depending on the application.

Selecting a LinkEdit

The related media is loaded by various APIs, by searching for the phrase on the relevant service. In the case of Wikipedia, it goes through "wikimedia/js/", and sends a request to this object. This is done live, after each search is typed, so there is some latency here. However, each service goes through a separate request, so the data for each service is loaded in parallel. The user can look at the first loaded one while the rest of the links load, so the perceived latency here is still acceptable.

The data for each service is fetched all at once, but it limits the results to a few (usually less than five) items. Thus, even though the granularity is low, this does not slow down the loading by much. Because it is hard to predict what the user will search for, there is no prefetching of results.

Various functions are called from there with the results of the search, eventually calling _16(). This function displays the search results: given the returned information, it creates the link elements, and sets relevant title and source URL. Clicking on the link element goes to a page with the information for that link filled out in editable text boxes. Clicking the "Link This Item" button calls the function setMediaItem() and starts the process of setting up the link with the server.

Sending InformationEdit

setMediaItem() calls a series of functions, but main work is done in _fA(). This first acquries information about the link selected using apture.linkProperties (apture is a global object created on page load, and linkProperties is set by the linker). It then sends this information about the link to the server using sendEncodedMessage(), which calls makeSenderEndpoint() with a payload. This is the main part that interacts with the server.

Displaying a Created LinkEdit

This is done similarly to the original popup: the included Javascript pulls in the links from the server, and hovering over the link gives the popup, using the timeouts and animation from before. For each link, a <script> element is added to the DOM under the <body> element. The "src" attribute of this <script> element uses the POST parameters (including the URL for the link, the key, and the site token unique to my site) to link in Javascript code that contains all of the information needed to build the popup (i.e. all of the textual contents), so there is no latency here. All of the loading is done when the page itself is loaded.


Here is a summary of what we found in the analysis:

  • Javascript is used to do nearly everything in this interaction, from AJAX requests to event handlers for opening popups and animating the divider. Because the webpage is not under Apture's control, it must use Javascript to make any changes to the page.
  • Most of the work is done in the browser, with some interaction with the server when saving the link information and when loading search results from other services.
  • Most of the interaction has relatively low latency because the majority of the interaction with the server is done at the time of page load (when the scripts are added to the page) and saving link information is relatively fast because the amount of information it must send is relatively small. However, there is noticeable latency when loading search results from other services, which has no prefetching because it is hard to predict which search results to fetch for ahead of time.
  • There are a few cases where browser limitations make this implementation more difficult. For getting highlighted text, Apture is forced to create two separate Selection classes to get around the inconsistencies in different browsers. Also, because of the hierarchical structure of HTML, it cannot allow a link over two paragraphs. Apture deals with this by simply not allowing such a link, which is a reasonable limitation.
  • The technique of loading in Javascript from a server to modify a page that it cannot directly change is a useful one, and often used by other blog plugins (such as Disqus).
  • The animation and mouseover delays used for the paragraph dividers is also interesting in the interplay of timeout functions. For example, if the mouse moves out of the divider, it must set a function to hide the divider in half a second, but if the mouse moves back, that function must be canceled by setting a boolean.

Ad blocker interference detected!

Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.