The beauty of Splash is that it uses right tools for the right things. Particularly, I am talking about the computer language selection. Splash uses the following languages:

  • Python - backend, agile, powerful and elegant language
  • Lua - scripts, very powerful and simple
  • JavaScript - used in Web engine

Currently, I am using all that languages and in my recent task I’ve faced with some interesting challenges.

getBoundingClientRect() vs getClientRects()[0]

I am working on HTMLElement class which allows you to manipulate with DOM HTML elements. And I’ve got the following problem. I need somehow get coordinates of the element. The most straightforward and portable solution (Splash is going to change its Web engine) is to use JavaScript. In JS there are two ways to get coordinates of element: Element.getBoundingClientRect() and Element.getClientRects().

getClientRects() method returns the list of all CSS layout border boxes of element. This list may contain rectangles which width and height is zero. getBoundingClientRect() method returns the smallest rectangle that includes all of the rectangles in list which is retrieved from getClientRects() of which the height or width is not zero.

For the most cases the first element of getClientRects() returned value will be the same as the result of getBoundingClientRect(). However, there are some situations where they can differ, e.g. elements which computed display CSS property is inline. Inline elements, such as <span>s create a box for each line they take. Let’s look on the Fig. 1.

Boundary Rectanges ExampleFig. 1

In this example I’ve highlighted boxes for <a> element What Every Computer Scientist Should Know About Floating-Point Arithmetic. The red bordered boxes are the rectangles returned by getClientRects() and the rectangles with the blue background is the result of getBoundingClientRect(). As this anchor element has inline display mode it creates a box for each line that it takes. Hence, it has two bounding client rectangles.

The both methods are useful and has its use cases. For example, if you want to get coordinates of the element in order to click on it you should better use getClientRects()[0]. And, if, for example, you want to take a screenshot of the element it’s better to use getBoundingClientRect().

Exceptions vs Flags

Another interesting thing that I should deal with is the error handling in Lua. In the world of Lua programming there are two ways to handle errors: exceptions and boolean flags.

Flag is the first return value of the called function which shows whether it did its work with no issues or not.

local ok, result = func()

if not ok:
  -- do something when the operation was unsuccessful
else:
  -- we got no problems with func
end

In Lua exceptions are thrown when the error is the reason of the user interaction when you cannot get the sane result and that error can be easily avoided, for example when user tried to send numbers to the function which requires string arguments. On the other hand, if error is the result of some interaction which cannot be avoided, let’s say user tries to open a file which is doesn’t exist, it can be returned as a boolean flag.

In my particular case I’m throwing an exception if user tries to get HTML element with non valid CSS selector and return a false flag if, let’s say, user tries to click on the element which has been removed from DOM.

The official Lua guide has an excellent article about error handling.

My work

I’m almost finished with HTMLElement class, there are small bugs, documentation and tests which should be written. The next week I’m going to create HTMLElements which is intended for manipulating collection of HTMLElements.