1.3.0
◀Back | Minified | Changelog | Cautionlog2012-07-26
v1.3.0 is out! This one has been a long time in the waiting and has some really nice changes.
Customizable Builds
Sugar just got a lot more customizable. The "core" package is now split by class, meaning you can now create custom Sugar builds that include only the specific classes you need. Date locales have also been moved out of the default and into their own package, as have other language-specific methods, helping to push down the default download size to just under 16kb. This process represents a major refactoring and makes Sugar now extremely modular.
Additionally, the ECMAScript shim methods (browser built-in methods like Array#indexOf
for browsers that don't support like IE) are now moved out into their own package as well. If you don't require legacy browser support (typically IE8 and below), you can remove this package and immediately save 1kb.
Sugar custom packages can be built here.
Enumerable Object Methods
Javascript has no internal concept of "Enumerables", but there are a number of enumerable methods on arrays that apply to objects as well, in the sense that they are "things that can be iterated over". Sugar previously provided an each
method. This update now provides 14 new array methods to also now work on objects as well. These methods are: any
, all
, none
, count
, find
, findAll
, sum
, average
, min
, max
, least
, most
, map
, and reduce
.
Sugar of course never modifies Object.prototype
, so these methods all exist as class methods. However, they are also available to extended objects, making them nearly as powerful as true Ruby-style hashes for a little extra work up front. This is especially evident when storing and manipulating JSON data:
Note that when callbacks are passed to enumerable methods, where they would previously be passed element, index
for arrays, they are now instead passed key, value
as the first 2 arguments. Last argument and this
keyword is still the object itself.
Also of note is that these methods (as well as each
and isEmpty
) now reside in the Array package (which can be thought of as the "Enumerables" package), which means that they won't be available without including that package.
Finally, a single method Object.size
was added as a shortcut to get the number of members in an object. "Size" was chosen as it is distinct from length
, which is not a method, but a property.
Date Ranges
A new concept for Sugar, "date ranges", as the name implies, are an object that define a specific range of time with a discernable start and end. They are created through the Date class by simply passing a start and end to Date.range
, which understands anything that Date.create
does:
All of these will result in valid ranges (note that if an argument is falsy it is assumed to be the current time). Once created, these ranges can be iterated over in various ways:
In the examples above, callback fn
will be passed a date object for each unit within the range, and will return an array containing every date object that was visited. Important to note is that the string format "2 weeks"
, and the each
shortcuts, which are equivalent, reset lower units and increment that unit directly. This means that eachDay
or every("day")
on a range starting at June 27th 4:25pm
will first visit June 27th 12:00:00am
and increment the date
by 1 on every iteration. In contrast, every((1).day())
, which is receiving a number in milliseconds, will begin at June 27th 4:25pm
and increment the date by 86400000 milliseconds on every iteration. Passing a number is more useful when precision is required.
Ranges also have a few other useful methods like contains
which will determine if the range contains a date or another date range. Ranges can also be manipulated with intersect
and union
which act much like their Array counterparts. Of note, however, is that Date Ranges only have a single start and end, so any gaps in 2 ranges that have been merged will effectively be "filled in".
Date Ranges reside in their own package, which is included in the default download. For a full method list, see the docs.
Date
A lot of updates have gone into the Date class, including some good performance optimizations. Date parsing formats are now scoped to their respective locale. Previously, when a language was set, its formats were added globally. While this did allow formats to be parsed without the proper locale code passed, it was a large performance penalty. This has now been changed so that the locale must be set correctly (either globally or by passing it to the date creation methods), however once set, the number of formats to lookup is significantly smaller, making for a faster result. Formats that are language-agnostic (such as numeric formats) are common to all locales.
This update also added the concept of a "cached format", which will take the last format that was successfully parsed and front load it, making operations that parse the same format repeatedly much faster.
Date output also has been enhanced, with 3 new output formats added for each locale: short
, long
, and full
. short
is the date alone, long
is the date and time, and full
is the full date and time with weekday and seconds. All 3 are available both through format
, and as instance shortcut methods and can be passed locale codes returning formats appropriate to their given locale:
The default format for Date.format()
is now the long
format.
Date manipulation also got some polishing. Date#reset
will now accept any unit, for example date.reset('day')
will reset the date and all smaller units. This method replaces Date#resetTime
, which is now deprecated.
Date#advance
will now accept a string format like "4 days"
, and, along with advancing methods like Date#addDays
, now accepts a 2nd boolean argument which will reset all units lower than the one being passed, similar to Date#set
:
Another cool addition is Date.past
, and Date.future
, which are alternate forms of Date.create
. They will similarly parse a date, but will assume past or future when there is ambiguity, allowing the parsing system to infer context that was previously impossible:
A good use for these methods would be a commenting system where such ambiguities are always in the past, or conversely a to-do list, where they are always in the future.
Date parsing now also handles a lot more formats. Time parsing is now much more robust and is fully supported in all locales, and includes time strings both before and after their corresponding date formats. Some pretty cool features like being able to parse out Chinese character numerals as numbers in dates and localized <date> at <time>
formats are now supported as well.
Timezone issues also got a long looking at and a number of issues, especially those dealing with traversing across DST (daylight savings time) have now been addressed.
Other date changes include:
- Added the format
just now
- Added the format
in 3 days
, etc. - Added the format
the 2nd Tuesday of November
, etc. - Added formats
last <weekday>
andnext <weekday>
in all locales - Passing locales codes like "it_IT" will now fall back to just
it
before bailing out. - Unknown languages codes in
Date.create
will simply return invalid instead of throwing an error. - Added support for time suffixes in Asian time strings ("時" etc)
- Various other fixes
Number
Methods in Math
are now mapped to Number
, making them easily accessible. This previously included floor
, ceil
, and round
, (all of which take a value for precision), but now includes abs
, pow
, sin
, asin
, cos
, acos
, tan
, atan
, exp
, pow
, sqrt
, and log
. Note that the base
parameter for log
defaults to Math.E
, returning the natural log of the number.
Other Changes
String#namespace
is now moved into the main String package, which takes a period-separated string and finds the corresponding namespace, by default starting from the global namespace.String#normalize
now lives in the "Language" package instead of the "Inflections" package.- Script detection methods (
String#hasHiragana
,String#hasHangul
, etc.) are likewise moved into the "Language" package. String#hankaku
,String#zenkaku
,String#hiragana
, andString#katakana
are also moved to the "Language" package.String#split
, which was added as a patch for discrepancies when splitting strings on regexes is now moved out of the main build and intolib/extra/
in the repo. Although useful, this patch was simply using up too much space to justify such an edge-case requirement. It also did not fit neatly into any packages, and so is being moved out.Array#has
is deprecated. UseArray#any
orArray#some
instead.Array#groupBy
no longer returns extended objects, and is fixed to no longer corrupt array lengths.- Enumerable array methods are now fixed to fuzzy match instances of classes as well as plain objects.
String#capitalize
now capitalizes after all special characters, not just after spaces.String#insert
now treats negative indexes likeString#slice
- Fixed issue with
String#decodeBase64
.