(function() {
'use strict';
/**
* angular attribute directive; parses ISO duration (`xs:duration`) strings.
*
* Transcludes markup, and creates a new scope with the following properties:
*
* - `years`, `months`, `weeks`, `days`, `hours`, `minutes`, `seconds`
* - `toString`: a function that returns the original text serialization of the duration
*
* see {@link ml-metrics} for an example
*
* @namespace ml-duration
*/
angular.module('ml.search')
.filter('duration', durationFilter)
.directive('mlDuration', mlDuration);
/**
* angular filter; parses ISO duration (`xs:duration`) strings and creates a string description.
*
* Usage: `myduration | duration[:options]`
*
* For example, `"P3Y4M75DT23H31M14.54S" | duration` will produce:
* "3 years, 4 months, 75 days, 23 hours, 31 minutes, and 14.54 seconds"
*
* Duration properties that aren't present will be suppressed. You can provide translations through the options:
*
* ```
* options = {
* year: 'year',
* years: 'years',
* month: 'month',
* months: 'months',
* week: 'week',
* weeks: 'weeks',
* day: 'day',
* days: 'days',
* hour: 'hour',
* hours: 'hours',
* minute: 'minute',
* minutes: 'minutes',
* second: 'second',
* seconds: 'seconds',
* }
* ```
* @namespace duration
*/
function durationFilter() {
return function(duration, options) {
duration = _.isObject( duration ) ? duration : parseDuration(duration);
var result = [];
var _options = {
year: 'year',
years: 'years',
month: 'month',
months: 'months',
week: 'week',
weeks: 'weeks',
day: 'day',
days: 'days',
hour: 'hour',
hours: 'hours',
minute: 'minute',
minutes: 'minutes',
second: 'second',
seconds: 'seconds'
};
angular.extend(_options, options);
_.each(['year', 'month', 'week', 'day', 'hour', 'minute', 'second'], function(category) {
var plural = category + 's';
if ( duration[ plural ] ) {
result.push(
duration[ plural ] + ' ' +
(duration[ plural ] > 1 ? _options[ plural ] : _options[ category ])
);
}
});
if (result.length > 1) {
var last = result.splice(result.length - 1, 1);
result = result.join(', ') + ', and ' + last[0];
return result;
} else {
return result[0] || '0 seconds';
}
};
}
function mlDuration() {
return {
restrict: 'A',
transclude: true,
scope: { mlDuration: '=' },
link: link
};
}
function link($scope, element, attrs, ctrl, transclude) {
$scope.$watch('mlDuration', function(newVal, oldVal) {
if (newVal) {
angular.extend($scope, {
duration: parseDuration(newVal)
});
}
});
transclude($scope, function(clone) {
element.append(clone);
});
}
function parseDuration(duration) {
// adapted from https://github.com/dordille/moment-isoduration
var pattern = [
'P(',
'(([0-9]*\\.?[0-9]*)Y)?',
'(([0-9]*\\.?[0-9]*)M)?',
'(([0-9]*\\.?[0-9]*)W)?',
'(([0-9]*\\.?[0-9]*)D)?',
')?',
'(T',
'(([0-9]*\\.?[0-9]*)H)?',
'(([0-9]*\\.?[0-9]*)M)?',
'(([0-9]*\\.?[0-9]*)S)?',
')?'
],
regex = new RegExp(pattern.join('')),
matches = duration.match(regex);
return {
years: parseFloat(matches[3]) || null,
months: parseFloat(matches[5]) || null,
weeks: parseFloat(matches[7]) || null,
days: parseFloat(matches[9]) || null,
hours: parseFloat(matches[12]) || null,
minutes: parseFloat(matches[14]) || null,
seconds: parseFloat(matches[16]) || null,
toString: function() {
return duration;
}
};
}
}());