Skip to content
Choose a tag to compare


@LeaVerou LeaVerou released this
· 268 commits to master since this release
Choose a tag to compare

It's been almost a year and a half since our last release, so this one is pretty huge. We'll try to summarize the changes the 330 (!) commits this release introduced below, but this list is far from comprehensive.

We strongly recommend that everyone upgrades to this version of Mavo, anything before that is fairly outdated at this point. We will not provide support for older versions, unless you discover a regression (i.e. something that was working in the old version that isn't working in the new one)

Backwards incompatible changes

  • The URL structure to use our CDN has slightly changed to be more consistent and predictable. If you were using e.g. to link to the latest stable version, you should now use The URL will now link to the latest development version (i.e. it is the same as the old which still works as well). If this seems confusing, just visit, answer the questions again and copy the provided URLs! You don't need to change anything if you're linking to a specific version, or to the latest dev version.
  • Date formatting is now done via an extra parameter on date functions (see "Date-based expressions" below)
  • mv-autosave without a value now defaults to 0 seconds (instant) instead of 3 seconds. However, we strongly recommend using it with a non-zero value for backends that generate an edit history (such as Github or Dropbox), otherwise you will end up with a huge, useless history.
  • The previously deprecated mv-optional attribute is now removed. Use mv-initial-items="0" instead
  • Microdata attributes (itemprop, itemscope, itemtype) are no longer supported for specifying Mavo properties. Mavo will still look in itemprop for a property name, if the property attribute is used without a value. The primary reason for this was that a) our research indicated that this syntax was very rarely used for specifying Mavo properties and b) People were often using Microdata in conjunction with Mavo, without expecting Mavo to do anything with these attributes, and then did not understand why this changed the way their apps were working.
  • The previously deprecated yes-* syntax in mv-bar has now been removed. Please use the new syntax only.

Mavo Actions

Probably the biggest major new feature is Mavo Actions. They allow you to create your own controls that modify the data in custom ways when activated, and they can be quite powerful. You can read all about them in the documentation.

These actions are sufficiently novel, that we published a peer-reviewed research paper about them at a top-tier Human-Computer Interaction conference (UIST). If it's your cup of tea, you can read the paper here.

Note that Mavo's own data manipulation controls (buttons for deleting items, adding new items etc) are now implemented with Actions as well!

Date-based expressions

  • Date formatting is now done via a second parameter in each date component function, not via the weird .formatType syntax we had before. E.g. instead of month(date).name you would write month(date, 'name') and instead of digits(2, month(date)), you would write month(date, '00'). For details, you can look at the documentation for these functions.
  • All date component functions (e.g. day() and days()) now return the number of milliseconds for that date component when called with no parameters, so you can do more readable comparisons of date intervals, (e.g. day() and days() both return 86400000). So something like birthday - $today > 6 * 86400000 can now be more readably written asbirthday - $today > 6 * days().
  • New duration() function for displaying time intervals in a readable way, based on a number of milliseconds (which is what subtracting dates returns in Mavo). E.g. duration(10000) will print out "10 seconds", duration(1000000) will print out "16 minutes" and duration(100000000) will print out "1 day".
  • Date formatting functions (as well as the new duration()) are localized based on the language of the Mavo app and not just that of the document root.


  • jsdelivr now used instead of for serving images uploaded to Github (if Github Pages is disabled), since rawgit is officially dead.
  • Uploads are now allowed on <a> and <link> elements with an mv-uploads attribute, not just on <img>, <audio>, <video> elements.
  • New mv-upload-url attribute to override the backend-provided URL for the upload.
  • For Plugin Developers: New hooks in upload popup, that make plugins like Cropper possible

UI changes

  • New UI for undoing deletion. Instead of "Item Deleted" elements all over the place, we now use a "toast" notification at the top.
  • Removed Mavo logo from toolbar

MavoScript changes

  • Better error reporting for expressions: Separate errors for syntax mistakes and errors during expression evaluation. The former only appear once in the console.
  • Smart property resolution now also works for "hidden" data that is not rendered on any HTML. This way you can have multiple Mavos that work on the same data and calculate things based on that data without having to add properties that you never intend to display.

New operators

  • New where operator and corresponding filter() function for filtering lists of values.
  • New in operator and corresponding has() function for searching in lists of values or groups
  • New .. operator for generating lists of integers, and corresponding range() function with more parameters (namely, a step)
  • New experimental by operator and corresponding groupBy() function, thanks to @jwass91

New special properties

  • New $item special property which always returns the closest collection item
  • New $all special property which can be used in two ways: a) By itself it returns all items of the closest collection b) after another property (like foo.$all), which returns all values of foo
  • New $this special property for the current group, useful in conjunction with where
  • Special properties are now also available without a $, albeit with lower priority (to avoid collisions with other types of variables). E.g. instead of $next, you can also use next. It's still recommended to use the $ anyway, for clarity.

New functions and improvements on existing functions

  • list() and group() functions for imitating the kinds of data that comes from collections and groups (for those who know JS or JSON: list(1, 2, 3) is analogous to [1, 2, 3] and group(name: 'Lea', age: 33) to {"name": "Lea", "age": 33})
  • New contains() function for searching entire objects and lists, thanks to @efeichen
  • New split() function for splitting text into a list (the opposite of join())
  • New random() function for generating random numbers
  • New median() function for calculating the median of a list of values
  • New phrase() function for custom localized text
  • Almost every Mavo function now works with lists of values as well, thanks to @efeichen
  • Optional n argument in first(n, list) and last(n, list) for how many first/last items to return (if omitted it defaults to 1)

Other changes

  • New mv-expressions-ignore attribute to ignore expression syntax (usually brackets) inside a specific attribute. E.g. to use a data URI with JSON inside mv-storage without its brackets interfering with expressions, you can just do mv-expressions-ignore="mv-storage". In the past, the only way to do this was to change the expression syntax for the entire element via mv-expressions.
  • Lots of improvements with the Github backend and the edit suggestion (pull request) flow, thanks to @jwass91
  • Simple properties can now contain arbitrary HTML that does not take part in the value of the property. E.g. if you want to have a static image inside your simple property, you can write <span property="foo">Hello <img src="foo.png"></span> and only the "Hello" will become editable.
  • aria-label is now dynamic and can be used to provide custom placeholders
  • Multiple property names are now supported in mv-alias thanks to @jwass91
  • Hundreds of bugfixes
  • Lots of performance improvements with expression evaluation
  • Improvements to memory management, thanks to @hopeful2
  • Lots of code cleanup and reorganization
  • In addition to people mentioned elsewhere in this log, I'd also like to credit: