Sugar | Javascript, sweetened.

May 2, 2012

Changelog | Cautionlog

A few semi-minor, but front-facing changes in this one:

String

String#truncate now has sensible defaults as well as different arguments. Previous arguments:

  • length The length to truncate to.
  • ellipsis The characters to indicate truncation ("...").
  • split Whether or not to split words on trucation (false by default).

Now are:

  • length
  • split (now true by default)
  • from New. Where to truncate from. Can be “left”, “middle”, or “right” (default).
  • ellipsis

Note that split is now true by default, which means that it will behave more like standard truncate methods by splitting to the exact character, even if it means it is the middle of a word. from allows truncation to happen in the middle or even on the left (“middle” is often useful for file URLs where the domain and filename/extension are the most important bits). ellipsis, which doesn’t often change, is now the last.

One more minor point to note is that previously the length of ellipsis would count against the length of the truncated string. In others words, if you truncated to 20 characters this would include 3 for the string "...". This is now changed so that the string will be truncated to 20 characters and then ellipsis will be appended. The motivation for this is the use case in which ellipsis can be HTML, in which case the string length (say <a onclick="showMore()">...</a>) would not be an accurate representation of how much space it takes up on the screen, and would be problematic if it counted against the string length.

Having four arguments for a method is less than ideal, but I weighed it against the option of removing an argument in favor of a different method name (in fact the motivation for adding throttle below), and also having an options hash. Ideally, the kind of short, utility methods that Sugar provides should have neither an options hash nor lengthy arguments — they should be as straightforward and easy to remember as possible. This case, however, was weighed against the confusion that new method names would introduce as well as whether the arguments were likely to stray from their defaults enough to warrant their own method name.

Function

Function#throttle functionality existed previously as Function#debounce with wait parameter set to false. This renaming should make it easier to remember what this method does, as well as bring the naming more in line with Underscore, which may be more familiar. It simply throttles a function to allow it to be executed only once per the designated number of milliseconds. debounce is simliar, but will wait the specified duration before executing.

Note also throttle’s similarity to Function#lazy. These 2 methods are in a sense counterparts. lazy will queue calls to a function (up to a limit if one is specified) and space them out so they are only executed once for a given duration. throttle, on the other hand, will only execute a maximum of once for that period without queueing. It is functionally identical to calling lazy with a limit of 1. Both methods have their own use cases and can be quite powerful if applied well.

Other

  • Object.isObject will now return true for extended objects.
  • Small refactoring of date parsing including support for .NET default date format.

March 26, 2012

Changelog | Cautionlog

The major change in this version is a big speed improvement for Array#unique, which now is an O(n) operation instead of O(n²). This method is also used internally in Array#union, Array#intersect, Array#min, Array#max, Array#most, and Array#least, so all these methods benefit from this. Many thanks to @ermouth for pointing out the issue and helping explore ideas for the solution.

This change also prompted a big internal refactoring with Object.equal. Although the effective result is only visible in a few edge cases, it means that Object.equal is now effectively “egal”, meaning the two values are equal if they are “not observably distinguishable”. This now brings Sugar in line with Underscore’s _.isEqual. See here for more on the concept of “egal”.

A few other minor bugfixes also found their way in, including custom date formats that override built-in formats.


March 22, 2012

New update to Sugar coming soon, but in the meantime I wanted to release something that I’ve been working on awhile.

First, I’ve added both Prototype and Underscore to the library reference page, which will now give a method-to-method direct comparison of both libs to Sugar.

While I think that’s nice, I’m using the underlying code for both those libs to do something even cooler. The new analyzer script is something I’ve been working on that when be dropped into any page, “hears” calls to methods in both Prototype and Underscore and provides tips and differences in syntax from that of Sugar. You can test out methods in the console and get inline code examples as well as a description of various differences in syntax.

But it gets better… the script will also call warning level logs that include a reference to the file and line number in question. This means that you can drop it into a page along with Sugar and detect and fix problems as they are called in the code. This should allow devs with old legacy applications they’d like to update to Sugar to get them running in a snap.

If you have unit tests or coverage tests for your app it’s even easier… just load the script in and let your code be called. There are a number of options that can be set simply by setting global flags, so even if you’re loading the script into an external site you can control the options.


March 7, 2012

The first thing to note is that as of this version I’ve added a new file to the repo called “CAUTION”. This file a filtered changelog with the biggest and most user-facing changes spelled out with their level of severity. If something breaks when updating check here first!. A couple of major API changes are happening with this release, so I figured now would be a good time to add this.

Alphanumeric Sorting

The first major change may be a bit subtle as it has no API associated with it, in fact 3 methods have now been deprecated: String#compare, Number#compare, and Date#compare. These methods have been junked in favor of a much more robust internal sort mechanism when sorting on strings.

First a note about compare. As it turned out, only strings had a special requirement for this in the first place, both other methods were basically doing a simple a < b comparison. What’s interesting about this is that Javascript calls the internal method valueOf when doing such comparisons. This means that an object that defines this method on it can be compared against other objects of the same type. This was in fact the original idea behind compare, but valueOf completely eliminates that need. Sugar now has unit tests asserting that any objects implementing a valueOf method are properly sorted across all browsers.

The major change that has come is to Array#sortBy which will now perform intelligent ordering when sorting on a string field. The details are here, but the gist is that there are now four fields defined on the Array class:

Array.AlphanumericSortOrder
Array.AlphanumericSortIgnore
Array.AlphanumericSortIgnoreCase
Array.AlphanumericSortIgnoreEquivalents

Order is a string defining the basic character order in which the sort should take place. If the characters of the strings being compared are found, the index within this sorting string will be used to determine order. If they are not found, it will fall back to standard Unicode order. Ignore is a regex used to prepare strings by removing punctuation and other characters that should not be sorted on. IgnoreCase is a boolean flag to ignore case when sorting. Finally Equivalents is a table of accented characters whose sort order should be equivalent to other characters. Most major Western European languages implement this to different degrees.

Although the customizability is exciting, the real feature here are the intelligent defaults. I’ve done a ton of research on the sort/collation patterns of all of the major Latin-based alphabets, and have determined a default that should be able to handle most of the major Latin-based langauges 100% out of the box. There are 2 notable exceptions - Polish and Scandanavian languages like Swedish and Norwegian. By removing 1 character (for Polish) or 2 (for Swedish, etc) from the equivalents table, however, this is easily handled for these languages as well.

There may be a few surprises in store for me with the exact language requirements, but I’m very happy with this system as it captures a lot of the complexity of complex sort collation algorithms with a very minimal footprint on the code and can easily be customized.

I’m also psyched that this change will once again add more robust support for non-Anglocentric devs who I feel have not had enough support in the past.

Number#duration

Much like Number#relative, this method added to the dates package will provide a simple way to convert numbers taken as milliseconds into a localized string:

(60 * 60 * 1000).duration();          > "1 hour ago"
(24 * 60 * 60 * 1000).duration();     > "1 day ago"
(8 * 24 * 60 * 60 * 1000).duration(); > "2 weeks ago"

This hooks into the dates locale system which is why it is added to the dates package despite being an extension of the Number class.

Other Changes

Object.merge now has more sensible defaults, with the deep merge flag as the 3rd parameter and the resolve parameter as the 4th. If you’re reading this note the change and be sure to update your code if there is any!

A number of other bugfixes also went into this release.


February 7, 2012

The most noteworthy update for v1.2.2 is a major performance optimization for Object.merge. This method is also the hook for Object.clone so this will make cloning faster as well. Shallow merges, which were previously 10x slower than jQuery’s $.extend are now nearly as fast, despite doing a number of checks that jQuery is leaving out, namely hasOwnProperty. Deep merges, which were about 5x slower before optimization are now almost twice as fast as jQuery.

Additionally deep cloning will now handle Date and RegExp objects as well, to prevent instance collisions (this is something that most other libs don’t even deal with). Alongside the optimizations for Object.merge were some other overall internal performance optimizations as well.

Also fixed an issue with UTC date parsing.


1 2 3 4 Next