var app = angular.module('plunker', ['timer']);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.callbackTimer = {};
$scope.callbackTimer.finished = function(user) {
//$scope.callbackTimer.status='COMPLETE!!';
//$scope.callbackTimer.callbackCount++;
//alert('Yay...finished - ' + user.callsign);
$scope.$apply();
};
$scope.StartUserTime = function (user){
angular.forEach($scope.userTimerCollection,function(elem,index){
if(elem.name === user.name)
return elem.counter;
});
};
$scope.userTimerCollection = [{
'name' : 'bpatel',
'callid' : 4,
'counter': '76'
},
{
'name' : 'rhill',
'callid' : 9,
'counter': '10'
},
{
'name' : 'zmohammed',
'callid' : 14,
'counter': '35'
},
{
'name' : 'apatel',
'callid' : 23,
'counter': '55'
}
];
$scope.users = [{
'name': 'bpatel',
'callsign': 'bp8978',
'status': 'BSY',
'counter': 76
}, {
'name': 'rhill',
'callsign': 'rh5653',
'status': 'TSTOP',
'counter': 10
}, {
'name': 'zmohammed',
'callsign': 'zm9930',
'status': 'STAGGED',
'counter': 35
}, {
'name': 'apatel',
'callsign': 'ap9878',
'status': 'ACK',
'counter': 55
}]
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link data-require="bootstrap@*" data-semver="3.2.0" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />
<script data-require="bootstrap@*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css" />
<script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>
<script src="timer.js"></script>
<script src="angular-filter.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div class="media block-update-card">
<div class="block-update-card status" ng-repeat="user in users">
<div class="h-status">
</div>
<div class="update-card-body">
<timer start-time="StartUserTime(user)"
countdown="StartUserTime(user)"
interval="1000"
finish-callback="callbackTimer.finished(user)">
<!-- {{seconds}} second{{secondsS}} -->
{{millis | date: "mm:ss"}}
<button class="btn btn-primary"
ng-show="millis == 0"
ng-click="this.start()">Start Again</button>
</timer>
<h4>{{user.name}}</h4>
<p>{{user.callsign}}
<span style="right: 0px;" class="label label-default">
{{user.status}}</span>
</p>
<timer start-time="StartUserTime(user)" countdown="StartUserTime(user)" interval="1000" finish-callback="callbackTimer.finished(user)">
<button class="btn btn-xs btn-danger" ng-disabled ="millis != 0" ng-click="this.start()">{{millis | date: "mm:ss"}}</button>
</timer>
</div>
</div>
</div>
</body>
</html>
.block-update-card {
height: 100%;
border: 1px #FFFFFF solid;
width: 380px;
float: left;
margin-left: 10px;
margin-top: 0;
padding: 0;
box-shadow: 1px 1px 8px #d8d8d8;
background-color: #FFFFFF;
}
.block-update-card .h-status {
width: 100%;
height: 7px;
background: repeating-linear-gradient(45deg, #606dbc, #606dbc 10px, #465298 10px, #465298 20px);
}
.block-update-card .v-status {
width: 5px;
height: 80px;
float: left;
margin-right: 5px;
background: repeating-linear-gradient(45deg, #606dbc, #606dbc 10px, #465298 10px, #465298 20px);
}
.block-update-card .update-card-MDimentions {
width: 80px;
height: 80px;
}
.block-update-card .update-card-body {
margin-top: 10px;
margin-left: 5px;
}
.block-update-card .update-card-body h4 {
color: #737373;
font-weight: bold;
font-size: 13px;
}
.block-update-card .update-card-body p {
color: #737373;
font-size: 12px;
}
.block-update-card .card-action-pellet {
padding: 5px;
}
.block-update-card .card-action-pellet div {
margin-right: 10px;
font-size: 15px;
cursor: pointer;
color: #dddddd;
}
.block-update-card .card-action-pellet div:hover {
color: #999999;
}
.block-update-card .card-bottom-status {
color: #a9a9aa;
font-weight: bold;
font-size: 14px;
border-top: #e0e0e0 1px solid;
padding-top: 5px;
margin: 0px;
}
.block-update-card .card-bottom-status:hover {
background-color: #dd4b39;
color: #FFFFFF;
cursor: pointer;
}
/*
Creating a block for social media buttons
*/
.card-body-social {
font-size: 30px;
margin-top: 10px;
}
.card-body-social .git {
color: black;
cursor: pointer;
margin-left: 10px;
}
.card-body-social .twitter {
color: #19C4FF;
cursor: pointer;
margin-left: 10px;
}
.card-body-social .google-plus {
color: #DD4B39;
cursor: pointer;
margin-left: 10px;
}
.card-body-social .facebook {
color: #49649F;
cursor: pointer;
margin-left: 10px;
}
.card-body-social .linkedin {
color: #007BB6;
cursor: pointer;
margin-left: 10px;
}
.music-card {
background-color: green;
}
/**
* angular-timer - v1.1.6 - 2014-07-01 7:37 AM
* https://github.com/siddii/angular-timer
*
* Copyright (c) 2014 Siddique Hameed
* Licensed MIT <https://github.com/siddii/angular-timer/blob/master/LICENSE.txt>
*/
var timerModule = angular.module('timer', [])
.directive('timer', ['$compile', function ($compile) {
return {
restrict: 'EAC',
replace: false,
scope: {
interval: '=interval',
startTimeAttr: '=startTime',
endTimeAttr: '=endTime',
countdownattr: '=countdown',
finishCallback: '&finishCallback',
autoStart: '&autoStart',
maxTimeUnit: '='
},
controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {
// Checking for trim function since IE8 doesn't have it
// If not a function, create tirm with RegEx to mimic native trim
if (typeof String.prototype.trim !== 'function') {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
//angular 1.2 doesn't support attributes ending in "-start", so we're
//supporting both "autostart" and "auto-start" as a solution for
//backward and forward compatibility.
$scope.autoStart = $attrs.autoStart || $attrs.autostart;
if ($element.html().trim().length === 0) {
$element.append($compile('<span>{{millis}}</span>')($scope));
} else {
$element.append($compile($element.contents())($scope));
}
$scope.startTime = null;
$scope.endTime = null;
$scope.timeoutId = null;
$scope.countdown = $scope.countdownattr && parseInt($scope.countdownattr, 10) >= 0 ? parseInt($scope.countdownattr, 10) : undefined;
$scope.isRunning = false;
$scope.$on('timer-start', function () {
$scope.start();
});
$scope.$on('timer-resume', function () {
$scope.resume();
});
$scope.$on('timer-stop', function () {
$scope.stop();
});
$scope.$on('timer-clear', function () {
$scope.clear();
});
$scope.$on('timer-set-countdown', function (e, countdown) {
$scope.countdown = countdown;
});
function resetTimeout() {
if ($scope.timeoutId) {
clearTimeout($scope.timeoutId);
}
}
$scope.start = $element[0].start = function () {
$scope.startTime = $scope.startTimeAttr ? new Date($scope.startTimeAttr) : new Date();
$scope.endTime = $scope.endTimeAttr ? new Date($scope.endTimeAttr) : null;
if (!$scope.countdown) {
$scope.countdown = $scope.countdownattr && parseInt($scope.countdownattr, 10) > 0 ? parseInt($scope.countdownattr, 10) : undefined;
}
resetTimeout();
tick();
$scope.isRunning = true;
};
$scope.resume = $element[0].resume = function () {
resetTimeout();
if ($scope.countdownattr) {
$scope.countdown += 1;
}
$scope.startTime = new Date() - ($scope.stoppedTime - $scope.startTime);
tick();
$scope.isRunning = true;
};
$scope.stop = $scope.pause = $element[0].stop = $element[0].pause = function () {
var timeoutId = $scope.timeoutId;
$scope.clear();
$scope.$emit('timer-stopped', {timeoutId: timeoutId, millis: $scope.millis, seconds: $scope.seconds, minutes: $scope.minutes, hours: $scope.hours, days: $scope.days});
};
$scope.clear = $element[0].clear = function () {
// same as stop but without the event being triggered
$scope.stoppedTime = new Date();
resetTimeout();
$scope.timeoutId = null;
$scope.isRunning = false;
};
$element.bind('$destroy', function () {
resetTimeout();
$scope.isRunning = false;
});
function calculateTimeUnits() {
// compute time values based on maxTimeUnit specification
if (!$scope.maxTimeUnit || $scope.maxTimeUnit === 'day') {
$scope.seconds = Math.floor(($scope.millis / 1000) % 60);
$scope.minutes = Math.floor((($scope.millis / (60000)) % 60));
$scope.hours = Math.floor((($scope.millis / (3600000)) % 24));
$scope.days = Math.floor((($scope.millis / (3600000)) / 24));
$scope.months = 0;
$scope.years = 0;
} else if ($scope.maxTimeUnit === 'second') {
$scope.seconds = Math.floor($scope.millis / 1000);
$scope.minutes = 0;
$scope.hours = 0;
$scope.days = 0;
$scope.months = 0;
$scope.years = 0;
} else if ($scope.maxTimeUnit === 'minute') {
$scope.seconds = Math.floor(($scope.millis / 1000) % 60);
$scope.minutes = Math.floor($scope.millis / 60000);
$scope.hours = 0;
$scope.days = 0;
$scope.months = 0;
$scope.years = 0;
} else if ($scope.maxTimeUnit === 'hour') {
$scope.seconds = Math.floor(($scope.millis / 1000) % 60);
$scope.minutes = Math.floor((($scope.millis / (60000)) % 60));
$scope.hours = Math.floor($scope.millis / 3600000);
$scope.days = 0;
$scope.months = 0;
$scope.years = 0;
} else if ($scope.maxTimeUnit === 'month') {
$scope.seconds = Math.floor(($scope.millis / 1000) % 60);
$scope.minutes = Math.floor((($scope.millis / (60000)) % 60));
$scope.hours = Math.floor((($scope.millis / (3600000)) % 24));
$scope.days = Math.floor((($scope.millis / (3600000)) / 24) % 30);
$scope.months = Math.floor((($scope.millis / (3600000)) / 24) / 30);
$scope.years = 0;
} else if ($scope.maxTimeUnit === 'year') {
$scope.seconds = Math.floor(($scope.millis / 1000) % 60);
$scope.minutes = Math.floor((($scope.millis / (60000)) % 60));
$scope.hours = Math.floor((($scope.millis / (3600000)) % 24));
$scope.days = Math.floor((($scope.millis / (3600000)) / 24) % 30);
$scope.months = Math.floor((($scope.millis / (3600000)) / 24 / 30) % 12);
$scope.years = Math.floor(($scope.millis / (3600000)) / 24 / 365);
}
// plural - singular unit decision
$scope.secondsS = $scope.seconds == 1 ? '' : 's';
$scope.minutesS = $scope.minutes == 1 ? '' : 's';
$scope.hoursS = $scope.hours == 1 ? '' : 's';
$scope.daysS = $scope.days == 1 ? '' : 's';
$scope.monthsS = $scope.months == 1 ? '' : 's';
$scope.yearsS = $scope.years == 1 ? '' : 's';
//add leading zero if number is smaller than 10
$scope.sseconds = $scope.seconds < 10 ? '0' + $scope.seconds : $scope.seconds;
$scope.mminutes = $scope.minutes < 10 ? '0' + $scope.minutes : $scope.minutes;
$scope.hhours = $scope.hours < 10 ? '0' + $scope.hours : $scope.hours;
$scope.ddays = $scope.days < 10 ? '0' + $scope.days : $scope.days;
$scope.mmonths = $scope.months < 10 ? '0' + $scope.months : $scope.months;
$scope.yyears = $scope.years < 10 ? '0' + $scope.years : $scope.years;
}
//determine initial values of time units and add AddSeconds functionality
if ($scope.countdownattr) {
$scope.millis = $scope.countdownattr * 1000;
$scope.addCDSeconds = $element[0].addCDSeconds = function (extraSeconds) {
$scope.countdown += extraSeconds;
$scope.$digest();
if (!$scope.isRunning) {
$scope.start();
}
};
$scope.$on('timer-add-cd-seconds', function (e, extraSeconds) {
$timeout(function () {
$scope.addCDSeconds(extraSeconds);
});
});
$scope.$on('timer-set-countdown-seconds', function (e, countdownSeconds) {
if (!$scope.isRunning) {
$scope.clear();
}
$scope.countdown = countdownSeconds;
$scope.millis = countdownSeconds * 1000;
calculateTimeUnits();
});
} else {
$scope.millis = 0;
}
calculateTimeUnits();
var tick = function () {
$scope.millis = new Date() - $scope.startTime;
var adjustment = $scope.millis % 1000;
if ($scope.endTimeAttr) {
$scope.millis = $scope.endTime - new Date();
adjustment = $scope.interval - $scope.millis % 1000;
}
if ($scope.countdownattr) {
$scope.millis = $scope.countdown * 1000;
}
if ($scope.millis < 0) {
$scope.stop();
$scope.millis = 0;
calculateTimeUnits();
if($scope.finishCallback) {
$scope.$eval($scope.finishCallback);
}
return;
}
calculateTimeUnits();
//We are not using $timeout for a reason. Please read here - https://github.com/siddii/angular-timer/pull/5
$scope.timeoutId = setTimeout(function () {
tick();
$scope.$digest();
}, $scope.interval - adjustment);
$scope.$emit('timer-tick', {timeoutId: $scope.timeoutId, millis: $scope.millis});
if ($scope.countdown > 0) {
$scope.countdown--;
}
else if ($scope.countdown <= 0) {
$scope.stop();
if($scope.finishCallback) {
$scope.$eval($scope.finishCallback);
}
}
};
if ($scope.autoStart === undefined || $scope.autoStart === true) {
$scope.start();
}
}]
};
}]);
/* commonjs package manager support (eg componentjs) */
if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){
module.exports = timerModule;
}
/**
* Bunch of useful filters for angularJS
* @version v0.4.7 - 2014-10-03 * @link https://github.com/a8m/angular-filter
* @author Ariel Mashraki <ariel@mashraki.co.il>
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
(function ( window, angular, undefined ) {
/*jshint globalstrict:true*/
'use strict';
var isDefined = angular.isDefined,
isUndefined = angular.isUndefined,
isFunction = angular.isFunction,
isString = angular.isString,
isNumber = angular.isNumber,
isObject = angular.isObject,
isArray = angular.isArray,
forEach = angular.forEach,
extend = angular.extend,
copy = angular.copy,
equals = angular.equals;
/**
* get an object and return array of values
* @param object
* @returns {Array}
*/
function toArray(object) {
return isArray(object) ? object :
Object.keys(object).map(function(key) {
return object[key];
});
}
/**
*
* @param value
* @returns {boolean}
*/
function isNull(value) {
return value === null;
}
/**
* return if object contains partial object
* @param partial{object}
* @param object{object}
* @returns {boolean}
*/
function objectContains(partial, object) {
var keys = Object.keys(partial);
return keys.map(function(el) {
return !(!object[el] || (object[el] != partial[el]));
}).indexOf(false) == -1;
}
/**
* search for approximate pattern in string
* @param word
* @param pattern
* @returns {*}
*/
function hasApproxPattern(word, pattern) {
if(pattern === '')
return word;
var index = word.indexOf(pattern.charAt(0));
if(index === -1)
return false;
return hasApproxPattern(word.substr(index+1), pattern.substr(1))
}
/**
* return the first n element of an array,
* if expression provided, is returns as long the expression return truthy
* @param array
* @param n {number}
* @param expression {$parse}
* @return array or single object
*/
function getFirstMatches(array, n, expression) {
var count = 0;
return array.filter(function(elm) {
var rest = isDefined(expression) ? (count < n && expression(elm)) : count < n;
count = rest ? count+1 : count;
return rest;
});
}
/**
* Polyfill to ECMA6 String.prototype.contains
*/
if (!String.prototype.contains) {
String.prototype.contains = function() {
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
}
/**
*
* @param num {Number}
* @param decimal {Number}
* @param $math
* @returns {Number}
*/
function convertToDecimal(num, decimal, $math){
return $math.round(num * $math.pow(10,decimal)) / ($math.pow(10,decimal));
}
/**
* @ngdoc filter
* @name a8m.angular
* @kind function
*
* @description
* reference to angular function
*/
angular.module('a8m.angular', [])
.filter('isUndefined', function () {
return function (input) {
return angular.isUndefined(input);
}
})
.filter('isDefined', function() {
return function (input) {
return angular.isDefined(input);
}
})
.filter('isFunction', function() {
return function (input) {
return angular.isFunction(input);
}
})
.filter('isString', function() {
return function (input) {
return angular.isString(input)
}
})
.filter('isNumber', function() {
return function (input) {
return angular.isNumber(input);
}
})
.filter('isArray', function() {
return function (input) {
return angular.isArray(input);
}
})
.filter('isObject', function() {
return function (input) {
return angular.isObject(input);
}
})
.filter('isEqual', function() {
return function (o1, o2) {
return angular.equals(o1, o2);
}
});
/**
* @ngdoc filter
* @name a8m.conditions
* @kind function
*
* @description
* reference to math conditions
*/
angular.module('a8m.conditions', [])
.filter({
isGreaterThan : isGreaterThanFilter,
'>' : isGreaterThanFilter,
isGreaterThanOrEqualTo : isGreaterThanOrEqualToFilter,
'>=' : isGreaterThanOrEqualToFilter,
isLessThan : isLessThanFilter,
'<' : isLessThanFilter,
isLessThanOrEqualTo : isLessThanOrEqualToFilter,
'<=' : isLessThanOrEqualToFilter,
isEqualTo : isEqualToFilter,
'==' : isEqualToFilter,
isNotEqualTo : isNotEqualToFilter,
'!=' : isNotEqualToFilter,
isIdenticalTo : isIdenticalToFilter,
'===' : isIdenticalToFilter,
isNotIdenticalTo : isNotIdenticalToFilter,
'!==' : isNotIdenticalToFilter
});
function isGreaterThanFilter() {
return function (input, check) {
return input > check;
};
}
function isGreaterThanOrEqualToFilter() {
return function (input, check) {
return input >= check;
};
}
function isLessThanFilter() {
return function (input, check) {
return input < check;
};
}
function isLessThanOrEqualToFilter() {
return function (input, check) {
return input <= check;
};
}
function isEqualToFilter() {
return function (input, check) {
return input == check;
};
}
function isNotEqualToFilter() {
return function (input, check) {
return input != check;
};
}
function isIdenticalToFilter() {
return function (input, check) {
return input === check;
};
}
function isNotIdenticalToFilter() {
return function (input, check) {
return input !== check;
};
}
/**
* @ngdoc filter
* @name isNull
* @kind function
*
* @description
* checks if value is null or not
* @return Boolean
*/
angular.module('a8m.is-null', [])
.filter('isNull', function () {
return function(input) {
return isNull(input);
}
});
/**
* @ngdoc filter
* @name after-where
* @kind function
*
* @description
* get a collection and properties object, and returns all of the items
* in the collection after the first that found with the given properties.
*
*/
angular.module('a8m.after-where', [])
.filter('afterWhere', function() {
return function (collection, object) {
collection = (isObject(collection)) ?
toArray(collection) :
collection;
if(!isArray(collection) || isUndefined(object))
return collection;
var index = collection.map( function( elm ) {
return objectContains(object, elm);
}).indexOf( true );
return collection.slice((index === -1) ? 0 : index);
}
});
/**
* @ngdoc filter
* @name after
* @kind function
*
* @description
* get a collection and specified count, and returns all of the items
* in the collection after the specified count.
*
*/
angular.module('a8m.after', [])
.filter('after', function() {
return function (collection, count) {
collection = (isObject(collection)) ?
toArray(collection) :
collection;
return (isArray(collection)) ?
collection.slice(count) :
collection;
}
});
/**
* @ngdoc filter
* @name before-where
* @kind function
*
* @description
* get a collection and properties object, and returns all of the items
* in the collection before the first that found with the given properties.
*
*/
angular.module('a8m.before-where', [])
.filter('beforeWhere', function() {
return function (collection, object) {
collection = (isObject(collection)) ?
toArray(collection) :
collection;
if(!isArray(collection) || isUndefined(object))
return collection;
var index = collection.map( function( elm ) {
return objectContains(object, elm);
}).indexOf( true );
return collection.slice(0, (index === -1) ? collection.length : ++index);
}
});
/**
* @ngdoc filter
* @name before
* @kind function
*
* @description
* get a collection and specified count, and returns all of the items
* in the collection before the specified count.
*
*/
angular.module('a8m.before', [])
.filter('before', function() {
return function (collection, count) {
collection = (isObject(collection)) ?
toArray(collection) :
collection;
return (isArray(collection)) ?
collection.slice(0, (!count) ? count : --count) :
collection;
}
});
/**
* @ngdoc filter
* @name concat
* @kind function
*
* @description
* get (array/object, object/array) and return merged collection
*
*/
angular.module('a8m.concat', [])
//TODO:unique option ? or use unique filter to filter result
.filter('concat', [function () {
return function (collection, joined) {
if (isUndefined(joined)) {
return collection;
}
if (isArray(collection)) {
return (isObject(joined)) ?
collection.concat(toArray(joined)) :
collection.concat(joined);
}
if (isObject(collection)) {
var array = toArray(collection);
return (isObject(joined)) ?
array.concat(toArray(joined)) :
array.concat(joined);
}
return collection;
};
}
]);
/**
* @ngdoc filter
* @name contains
* @kind function
*
* @description
* Checks if given expression is present in one or more object in the collection
*/
angular.module('a8m.contains', [])
.filter({
contains: ['$parse', containsFilter],
some: ['$parse', containsFilter]
});
function containsFilter( $parse ) {
return function (collection, expression) {
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(expression)) {
return true;
}
return collection.some( function(elm) {
return (isObject(elm) || isFunction(expression)) ?
$parse(expression)(elm) :
elm === expression;
});
}
}
/**
* @ngdoc filter
* @name countBy
* @kind function
*
* @description
* Sorts a list into groups and returns a count for the number of objects in each group.
*/
angular.module('a8m.count-by', [])
.filter('countBy', [ '$parse', function ( $parse ) {
return function (collection, property) {
var result = {},
get = $parse(property),
prop;
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(property)) {
return collection;
}
collection.forEach( function( elm ) {
prop = get(elm);
if(!result[prop]) {
result[prop] = 0;
}
result[prop]++;
});
return result;
}
}]);
/**
* @ngdoc filter
* @name every
* @kind function
*
* @description
* Checks if given expression is present in all members in the collection
*
*/
angular.module('a8m.every', [])
.filter('every', ['$parse', function($parse) {
return function (collection, expression) {
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(expression)) {
return true;
}
return collection.every( function(elm) {
return (isObject(elm) || isFunction(expression)) ?
$parse(expression)(elm) :
elm === expression;
});
}
}]);
/**
* @ngdoc filter
* @name filterBy
* @kind function
*
* @description
* filter by specific properties, avoid the rest
*/
angular.module('a8m.filter-by', [])
.filter('filterBy', ['$parse', function( $parse ) {
return function(collection, properties, search) {
var comparator;
search = (isString(search) || isNumber(search)) ?
String(search).toLowerCase() : undefined;
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(search)) {
return collection;
}
return collection.filter(function(elm) {
return properties.some(function(prop) {
/**
* check if there is concatenate properties
* example:
* object: { first: 'foo', last:'bar' }
* filterBy: ['first + last'] => search by full name(i.e 'foo bar')
*/
if(!~prop.indexOf('+')) {
comparator = $parse(prop)(elm)
} else {
var propList = prop.replace(new RegExp('\\s', 'g'), '').split('+');
comparator = propList.reduce(function(prev, cur, index) {
return (index === 1) ? $parse(prev)(elm) + ' ' + $parse(cur)(elm) :
prev + ' ' + $parse(cur)(elm);
});
}
return (isString(comparator) || isNumber(comparator)) ?
String(comparator).toLowerCase().contains(search) :
false;
})
});
}
}]);
/**
* @ngdoc filter
* @name first
* @kind function
*
* @description
* Gets the first element or first n elements of an array
* if callback is provided, is returns as long the callback return truthy
*/
angular.module('a8m.first', [])
.filter('first', ['$parse', function( $parse ) {
return function(collection) {
var n,
getter,
args;
collection = (isObject(collection)) ? toArray(collection) :
collection;
if(!isArray(collection)) {
return collection;
}
args = Array.prototype.slice.call(arguments, 1);
n = (isNumber(args[0])) ? args[0] : 1;
getter = (!isNumber(args[0])) ? args[0] : (!isNumber(args[1])) ? args[1] : undefined;
return (args.length) ? getFirstMatches(collection, n,(getter) ? $parse(getter) : getter) :
collection[0];
}
}]);
/**
* @ngdoc filter
* @name flatten
* @kind function
*
* @description
* Flattens a nested array (the nesting can be to any depth).
* If you pass shallow, the array will only be flattened a single level
*/
angular.module('a8m.flatten', [])
.filter('flatten', function () {
return function(collection, shallow) {
shallow = shallow || false;
collection = (isObject(collection)) ? toArray(collection)
: collection;
if(!isArray(collection)) {
return collection;
}
return (!shallow) ? flatten(collection, 0) :
[].concat.apply([], collection);
}
});
/**
* flatten nested array (the nesting can be to any depth).
* @param array {Array}
* @param i {int}
* @returns {Array}
* @private
*/
function flatten(array, i) {
i = i || 0;
if(i >= array.length)
return array;
if(isArray(array[i])) {
return flatten(array.slice(0,i)
.concat(array[i], array.slice(i+1)), i);
}
return flatten(array, i+1);
}
/**
* @ngdoc filter
* @name fuzzyByKey
* @kind function
*
* @description
* fuzzy string searching by key
*/
angular.module('a8m.fuzzy-by', [])
.filter('fuzzyBy', ['$parse', function ( $parse ) {
return function (collection, property, search, csensitive) {
var sensitive = csensitive || false,
prop, getter;
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(property)
|| isUndefined(search)) {
return collection;
}
getter = $parse(property);
return collection.filter(function(elm) {
prop = getter(elm);
if(!isString(prop)) {
return false;
}
prop = (sensitive) ? prop : prop.toLowerCase();
search = (sensitive) ? search : search.toLowerCase();
return hasApproxPattern(prop, search) !== false
})
}
}]);
/**
* @ngdoc filter
* @name fuzzy
* @kind function
*
* @description
* fuzzy string searching for array of strings, objects
*/
angular.module('a8m.fuzzy', [])
.filter('fuzzy', function () {
return function (collection, search, csensitive) {
var sensitive = csensitive || false;
collection = (isObject(collection)) ? toArray(collection) : collection;
if(!isArray(collection) || isUndefined(search)) {
return collection;
}
search = (sensitive) ? search : search.toLowerCase();
return collection.filter(function(elm) {
if(isString(elm)) {
elm = (sensitive) ? elm : elm.toLowerCase();
return hasApproxPattern(elm, search) !== false
}
return (isObject(elm)) ? _hasApproximateKey(elm, search) : false;
});
/**
* checks if object has key{string} that match
* to fuzzy search pattern
* @param object
* @param search
* @returns {boolean}
* @private
*/
function _hasApproximateKey(object, search) {
var properties = Object.keys(object),
prop, flag;
return 0 < properties.filter(function (elm) {
prop = object[elm];
//avoid iteration if we found some key that equal[performance]
if(flag) return true;
if (isString(prop)) {
prop = (sensitive) ? prop : prop.toLowerCase();
return flag = (hasApproxPattern(prop, search) !== false);
}
return false;
}).length;
}
}
});
/**
* @ngdoc filter
* @name groupBy
* @kind function
*
* @description
* Create an object composed of keys generated from the result of running each element of a collection,
* each key is an array of the elements.
*/
angular.module('a8m.group-by', [ 'a8m.filter-watcher' ])
.filter('groupBy', [ '$parse', 'filterWatcher', function ( $parse, filterWatcher ) {
return function (collection, property) {
var result,
get = $parse(property),
prop;
if(!isObject(collection) || isUndefined(property)) {
return collection;
}
//Add collection instance to watch list
result = filterWatcher.$watch('groupBy', collection);
forEach( collection, function( elm ) {
prop = get(elm);
if(!result[prop]) {
result[prop] = [];
}
if(result[prop].indexOf( elm ) === -1) {
result[prop].push(elm);
}
});
//kill instance
filterWatcher.$destroy('groupBy', collection);
return result;
}
}]);
/**
* @ngdoc filter
* @name isEmpty
* @kind function
*
* @description
* get collection or string and return if it empty
*/
angular.module('a8m.is-empty', [])
.filter('isEmpty', function () {
return function(collection) {
return (isObject(collection)) ?
!toArray(collection).length :
!collection.length;
}
});
/**
* @ngdoc filter
* @name last
* @kind function
*
* @description
* Gets the last element or last n elements of an array
* if callback is provided, is returns as long the callback return truthy
*/
angular.module('a8m.last', [])
.filter('last', ['$parse', function( $parse ) {
return function(collection) {
var n,
getter,
args,
//cuz reverse change our src collection
//and we don't want side effects
reversed = copy(collection);
reversed = (isObject(reversed)) ? toArray(reversed) :
reversed;
if(!isArray(reversed)) {
return reversed;
}
args = Array.prototype.slice.call(arguments, 1);
n = (isNumber(args[0])) ? args[0] : 1;
getter = (!isNumber(args[0])) ? args[0] : (!isNumber(args[1])) ? args[1] : undefined;
return (args.length) ?
//send reversed collection as arguments, and reverse it back as result
getFirstMatches(reversed.reverse(), n,(getter) ? $parse(getter) : getter).reverse() :
//get the last element
reversed[reversed.length-1];
}
}]);
/**
* @ngdoc filter
* @name map
* @kind function
*
* @description
* Returns a new collection of the results of each expression execution.
*/
angular.module('a8m.map', [])
.filter('map', ['$parse', function($parse) {
return function (collection, expression) {
collection = (isObject(collection)) ?
toArray(collection) : collection;
if(!isArray(collection) || isUndefined(expression)) {
return collection;
}
return collection.map(function (elm) {
return $parse(expression)(elm);
});
}
}]);
/**
* @ngdoc filter
* @name omit
* @kind function
*
* @description
* filter collection by expression
*/
angular.module('a8m.omit', [])
.filter('omit', ['$parse', function($parse) {
return function (collection, expression) {
collection = (isObject(collection)) ?
toArray(collection) : collection;
if(!isArray(collection) || isUndefined(expression)) {
return collection;
}
return collection.filter(function (elm) {
return !($parse(expression)(elm));
});
}
}]);
/**
* @ngdoc filter
* @name omit
* @kind function
*
* @description
* filter collection by expression
*/
angular.module('a8m.pick', [])
.filter('pick', ['$parse', function($parse) {
return function (collection, expression) {
collection = (isObject(collection)) ?
toArray(collection) : collection;
if(!isArray(collection) || isUndefined(expression)) {
return collection;
}
return collection.filter(function (elm) {
return $parse(expression)(elm);
});
}
}]);
/**
* @ngdoc filter
* @name removeWith
* @kind function
*
* @description
* get collection and properties object, and removed elements
* with this properties
*/
angular.module('a8m.remove-with', [])
.filter('removeWith', function() {
return function (collection, object) {
if(isUndefined(object)) {
return collection;
}
collection = (isObject(collection)) ?
toArray(collection) : collection;
return collection.filter(function (elm) {
return !objectContains(object, elm);
});
}
});
/**
* @ngdoc filter
* @name remove
* @kind function
*
* @description
* remove specific members from collection
*/
angular.module('a8m.remove', [])
.filter('remove', function () {
return function (collection) {
collection = (isObject(collection)) ? toArray(collection) : collection;
var args = Array.prototype.slice.call(arguments, 1);
if(!isArray(collection)) {
return collection;
}
return collection.filter( function( member ) {
return !args.some(function(nest) {
return equals(nest, member);
})
});
}
});
/**
* @ngdoc filter
* @name reverse
* @kind function
*
* @description
* Reverses a string or collection
*/
angular.module('a8m.reverse', [])
.filter('reverse',[ function () {
return function (input) {
input = (isObject(input)) ? toArray(input) : input;
if(isString(input)) {
return input.split('').reverse().join('');
}
return (isArray(input)) ? input.reverse() : input;
}
}]);
/**
* @ngdoc filter
* @name searchField
* @kind function
*
* @description
* for each member, join several strings field and add them to
* new field called 'searchField' (use for search filtering)
*/
angular.module('a8m.search-field', [])
.filter('searchField', ['$parse', function ($parse) {
return function (collection) {
var get, field;
collection = (isObject(collection)) ? toArray(collection) : collection;
var args = Array.prototype.slice.call(arguments, 1);
if(!isArray(collection) || !args.length) {
return collection;
}
return collection.map(function(member) {
field = args.map(function(field) {
get = $parse(field);
return get(member);
}).join(' ');
return extend(member, { searchField: field });
});
}
}]);
/**
* @ngdoc filter
* @name toArray
* @kind function
*
* @description
* Convert objects into stable arrays.
* if addKey set to true,the filter also attaches a new property
* $key to the value containing the original key that was used in
* the object we are iterating over to reference the property
*/
angular.module('a8m.to-array', [])
.filter('toArray', function() {
return function (collection, addKey) {
if(!isObject(collection)) {
return collection;
}
return (!addKey) ? toArray(collection) :
Object.keys(collection).map(function (key) {
return extend(collection[key], { $key: key });
});
}
});
/**
* @ngdoc filter
* @name unique/uniq
* @kind function
*
* @description
* get collection and filter duplicate members
* if uniqueFilter get a property(nested to) as argument it's
* filter by this property as unique identifier
*/
angular.module('a8m.unique', [])
.filter({
unique: ['$parse', uniqFilter],
uniq: ['$parse', uniqFilter]
});
function uniqFilter($parse) {
return function (collection, property) {
collection = (isObject(collection)) ? toArray(collection) : collection;
if (!isArray(collection)) {
return collection;
}
//store all unique identifiers
var uniqueItems = [],
get = $parse(property);
return (isUndefined(property)) ?
//if it's kind of primitive array
collection.filter(function (elm, pos, self) {
return self.indexOf(elm) === pos;
}) :
//else compare with equals
collection.filter(function (elm) {
var prop = get(elm);
if(some(uniqueItems, prop)) {
return false;
}
uniqueItems.push(prop);
return true;
});
//checked if the unique identifier is already exist
function some(array, member) {
if(isUndefined(member)) {
return false;
}
return array.some(function(el) {
return equals(el, member);
});
}
}
}
/**
* @ngdoc filter
* @name where
* @kind function
*
* @description
* of each element in a collection to the given properties object,
* returning an array of all elements that have equivalent property values.
*
*/
angular.module('a8m.where', [])
.filter('where', function() {
return function (collection, object) {
if(isUndefined(object)) {
return collection;
}
collection = (isObject(collection)) ?
toArray(collection) : collection;
return collection.filter(function (elm) {
return objectContains(object, elm);
});
}
});
/**
* @ngdoc filter
* @name xor
* @kind function
*
* @description
* Exclusive or filter by expression
*/
angular.module('a8m.xor', [])
.filter('xor', ['$parse', function($parse) {
return function (col1, col2, expression) {
expression = expression || false;
col1 = (isObject(col1)) ? toArray(col1) : col1;
col2 = (isObject(col2)) ? toArray(col2) : col2;
if(!isArray(col1) || !isArray(col2)) return col1;
return col1.concat(col2)
.filter(function(elm) {
return !(some(elm, col1) && some(elm, col2));
});
function some(el, col) {
var getter = $parse(expression);
return col.some(function(dElm) {
return expression ?
equals(getter(dElm), getter(el)) :
equals(dElm, el);
})
}
}
}]);
/**
* @ngdoc filter
* @name formatBytes
* @kind function
*
* @description
* Convert bytes into appropriate display
* 1024 bytes => 1 KB
*/
angular.module('a8m.math.byteFmt', ['a8m.math'])
.filter('byteFmt', ['$math', function ($math) {
return function (bytes, decimal) {
if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
isNumber(bytes) && isFinite(bytes)) {
if(bytes < 1024) { // within 1 KB so B
return convertToDecimal(bytes, decimal, $math) + ' B';
} else if(bytes < 1048576) { // within 1 MB so KB
return convertToDecimal((bytes / 1024), decimal, $math) + ' KB';
} else if(bytes < 1073741824){ // within 1 GB so MB
return convertToDecimal((bytes / 1048576), decimal, $math) + ' MB';
} else { // GB or more
return convertToDecimal((bytes / 1073741824), decimal, $math) + ' GB';
}
} else {
return "NaN";
}
}
}]);
/**
* @ngdoc filter
* @name degrees
* @kind function
*
* @description
* Convert angle from radians to degrees
*
*/
angular.module('a8m.math.degrees', ['a8m.math'])
.filter('degrees', ['$math', function ($math) {
return function (radians, decimal) {
// if decimal is not an integer greater than -1, we cannot do. quit with error "NaN"
// if degrees is not a real number, we cannot do also. quit with error "NaN"
if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
isNumber(radians) && isFinite(radians)) {
var degrees = (radians * 180) / $math.PI;
return $math.round(degrees * $math.pow(10,decimal)) / ($math.pow(10,decimal));
} else {
return "NaN";
}
}
}]);
/**
* @ngdoc filter
* @name formatBytes
* @kind function
*
* @description
* Convert bytes into appropriate display
* 1024 kilobytes => 1 MB
*/
angular.module('a8m.math.kbFmt', ['a8m.math'])
.filter('kbFmt', ['$math', function ($math) {
return function (bytes, decimal) {
if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
isNumber(bytes) && isFinite(bytes)) {
if(bytes < 1024) { // within 1 MB so KB
return convertToDecimal(bytes, decimal, $math) + ' KB';
} else if(bytes < 1048576) { // within 1 GB so MB
return convertToDecimal((bytes / 1024), decimal, $math) + ' MB';
} else {
return convertToDecimal((bytes / 1048576), decimal, $math) + ' GB';
}
} else {
return "NaN";
}
}
}]);
/**
* @ngdoc module
* @name math
* @description
* reference to global Math object
*/
angular.module('a8m.math', [])
.factory('$math', ['$window', function ($window) {
return $window.Math;
}]);
/**
* @ngdoc filter
* @name max
* @kind function
*
* @description
* Math.max
*
*/
angular.module('a8m.math.max', ['a8m.math'])
.filter('max', ['$math', function ($math) {
return function (input) {
return (isArray(input)) ?
$math.max.apply($math, input) :
input;
}
}]);
/**
* @ngdoc filter
* @name min
* @kind function
*
* @description
* Math.min
*
*/
angular.module('a8m.math.min', ['a8m.math'])
.filter('min', ['$math', function ($math) {
return function (input) {
return (isArray(input)) ?
$math.min.apply($math, input) :
input;
}
}]);
/**
* @ngdoc filter
* @name Percent
* @kind function
*
* @description
* percentage between two numbers
*
*/
angular.module('a8m.math.percent', ['a8m.math'])
.filter('percent', ['$math', '$window', function ($math, $window) {
return function (input, divided, round) {
var divider = (isString(input)) ? $window.Number(input) : input;
divided = divided || 100;
round = round || false;
if (!isNumber(divider) || $window.isNaN(divider)) return input;
return (round) ? $math.round((divider / divided) * 100) :
((divider / divided) * 100);
}
}]);
/**
* @ngdoc filter
* @name toRadians
* @kind function
*
* @description
* Convert angle from degrees to radians
*
*/
angular.module('a8m.math.radians', ['a8m.math'])
.filter('radians', ['$math', function ($math) {
return function (degrees, decimal) {
// if decimal is not an integer greater than -1, we cannot do. quit with error "NaN"
// if degrees is not a real number, we cannot do also. quit with error "NaN"
if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
isNumber(degrees) && isFinite(degrees)) {
var radians = (degrees * 3.14159265359) / 180;
return $math.round(radians * $math.pow(10,decimal)) / ($math.pow(10,decimal));
} else {
return "NaN";
}
}
}]);
/**
* @ngdoc filter
* @name Radix
* @kind function
*
* @description
* converting decimal numbers to different bases(radix)
*/
angular.module('a8m.math.radix', [])
.filter('radix', function () {
return function (input, radix) {
var RANGE = /^[2-9]$|^[1-2]\d$|^3[0-6]$/;
if(!isNumber(input) || !RANGE.test(radix)) {
return input;
}
return input.toString(radix).toUpperCase();
}
});
/**
* @ngdoc filter
* @name formatBytes
* @kind function
*
* @description
* Convert number into abbreviations.
* i.e: K for one thousand, M for Million, B for billion
* e.g: number of users:235,221, decimal:1 => 235.2 K
*/
angular.module('a8m.math.shortFmt', ['a8m.math'])
.filter('shortFmt', ['$math', function ($math) {
return function (number, decimal) {
if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
isNumber(number) && isFinite(number)){
if(number < 1e3) {
return number;
} else if(number < 1e6) {
return convertToDecimal((number / 1e3), decimal, $math) + ' K';
} else if(number < 1e9){
return convertToDecimal((number / 1e6), decimal, $math) + ' M';
} else {
return convertToDecimal((number / 1e9), decimal, $math) + ' B';
}
}else{
return "NaN";
}
}
}]);
/**
* @ngdoc filter
* @name sum
* @kind function
*
* @description
* Sum up all values within an array
*
*/
angular.module('a8m.math.sum', [])
.filter('sum', function () {
return function (input, initial) {
return (!isArray(input)) ? input :
input.reduce(function(prev, curr) {
return prev + curr;
}, initial || 0);
}
});
/**
* @ngdoc filter
* @name endsWith
* @kind function
*
* @description
* checks whether string ends with the ends parameter.
*/
angular.module('a8m.ends-with', [])
.filter('endsWith', function () {
return function (input, ends, csensitive) {
var sensitive = csensitive || false,
position;
if(!isString(input) || isUndefined(ends)) {
return input;
}
input = (sensitive) ? input : input.toLowerCase();
position = input.length - ends.length;
return input.indexOf((sensitive) ? ends : ends.toLowerCase(), position) !== -1;
}
});
/**
* @ngdoc filter
* @name ltrim
* @kind function
*
* @description
* Left trim. Similar to trimFilter, but only for left side.
*/
angular.module('a8m.ltrim', [])
.filter('ltrim', function () {
return function(input, chars) {
var trim = chars || '\\s';
if(!isString(input)) {
return input;
}
return input.replace(new RegExp('^' + trim + '+'), '');
}
});
/**
* @ngdoc filter
* @name repeat
* @kind function
*
* @description
* Repeats a string n times
*/
angular.module('a8m.repeat', [])
.filter('repeat',[ function () {
return function (input, n, separator) {
var times = ~~n;
if(!isString(input)) {
return input;
}
return (!times) ? input : strRepeat(input, --n, separator || '');
}
}]);
/**
* Repeats a string n times with given separator
* @param str string to repeat
* @param n number of times
* @param sep separator
* @returns {*}
*/
function strRepeat(str, n, sep) {
if(!n) {
return str;
}
return str + sep + strRepeat(str, --n, sep);
}
/**
* @ngdoc filter
* @name rtrim
* @kind function
*
* @description
* Right trim. Similar to trimFilter, but only for right side.
*/
angular.module('a8m.rtrim', [])
.filter('rtrim', function () {
return function(input, chars) {
var trim = chars || '\\s';
if(!isString(input)) {
return input;
}
return input.replace(new RegExp(trim + '+$'), '');
}
});
/**
* @ngdoc filter
* @name slugify
* @kind function
*
* @description
* remove spaces from string, replace with "-" or given argument
*/
angular.module('a8m.slugify', [])
.filter('slugify',[ function () {
return function (input, sub) {
var replace = sub || '-';
if(isString(input)) {
return input.toLowerCase()
.replace(/\s+/g, replace);
}
return input;
}
}]);
/**
* @ngdoc filter
* @name startWith
* @kind function
*
* @description
* checks whether string starts with the starts parameter.
*/
angular.module('a8m.starts-with', [])
.filter('startsWith', function () {
return function (input, start, csensitive) {
var sensitive = csensitive || false;
if(!isString(input) || isUndefined(start)) {
return input;
}
input = (sensitive) ? input : input.toLowerCase();
return !input.indexOf((sensitive) ? start : start.toLowerCase());
}
});
/**
* @ngdoc filter
* @name stringular
* @kind function
*
* @description
* get string with {n} and replace match with enumeration values
*/
angular.module('a8m.stringular', [])
.filter('stringular', function () {
return function(input) {
var args = Array.prototype.slice.call(arguments, 1);
return input.replace(/{(\d+)}/g, function (match, number) {
return isUndefined(args[number]) ? match : args[number];
});
}
});
/**
* @ngdoc filter
* @name stripTags
* @kind function
*
* @description
* strip html tags from string
*/
angular.module('a8m.strip-tags', [])
.filter('stripTags', function () {
return function(input) {
if(isString(input)) {
return input.replace(/<\S[^><]*>/g, '');
}
return input;
}
});
/**
* @ngdoc filter
* @name trim
* @kind function
*
* @description
* Strip whitespace (or other characters) from the beginning and end of a string
*/
angular.module('a8m.trim', [])
.filter('trim', function () {
return function(input, chars) {
var trim = chars || '\\s';
if(!isString(input)) {
return input;
}
return input.replace(new RegExp('^' + trim + '+|' + trim + '+$', 'g'), '');
}
});
/**
* @ngdoc filter
* @name truncate
* @kind function
*
* @description
* truncates a string given a specified length, providing a custom string to denote an omission.
*/
angular.module('a8m.truncate', [])
.filter('truncate', function () {
return function(input, length, suffix, preserve) {
length = isUndefined(length) ? input.length : length;
preserve = preserve || false;
suffix = suffix || '';
if(!isString(input) || (input.length <= length)) return input;
return input.substring(0, (preserve) ?
((input.indexOf(' ', length) === -1) ? input.length : input.indexOf(' ', length)) :
length) + suffix;
};
});
/**
* @ngdoc filter
* @name ucfirst
* @kind function
*
* @description
* ucfirst
*
*/
angular.module('a8m.ucfirst', [])
.filter('ucfirst', [function() {
return function(input) {
return angular.isString(input) ? input.split(' ')
.map(function (char) {
return char.charAt(0).toUpperCase() + char.substring(1);
}).join(' ') : input;
}
}]);
/**
* @ngdoc filter
* @name uriEncode
* @kind function
*
* @description
* get string as parameter and return encoded string
*/
angular.module('a8m.uri-encode', [])
.filter('uriEncode',['$window', function ($window) {
return function (input) {
if(isString(input)) {
return $window.encodeURI(input);
}
return input;
}
}]);
/**
* @ngdoc filter
* @name wrap
* @kind function
*
* @description
* Wrap a string with another string
*/
angular.module('a8m.wrap', [])
.filter('wrap', function () {
return function(input, wrap, ends) {
if(!isString(input) || isUndefined(wrap)) {
return input;
}
return [wrap, input, ends || wrap].join('');
}
});
/**
* @ngdoc provider
* @name filterWatcher
* @kind function
*
* @description
* filterWatchers is a _privateProvider
* It's created to solve the problem of $rootScope:infdig(Infinite $digest loop) when using
* some filters on the view.
*/
angular.module('a8m.filter-watcher', [])
.provider('filterWatcher', function() {
var filterPrefix = '_$$';
/**
* @description
* change the prefix name for filters on watch phase
* @param prefix
* @returns {filterWatcher}
*/
this.setPrefix = function(prefix) {
filterPrefix = prefix;
return this;
};
this.$get = ['$window', function($window) {
var $$timeout = $window.setTimeout;
/**
* @description
* return the filter full name
* @param name
* @returns {string}
* @private
*/
function _getFullName(name) {
return filterPrefix + name;
}
/**
* @description
* return whether or not this object is watched in current phase
* @param fName
* @param object
* @returns {boolean}
* @private
*/
function _isWatched(fName, object) {
return isDefined(object[fName]);
}
/**
* @description
* return the object.$$filterName instance in current phase
* @param name
* @param object
* @private
*/
function _watch(name, object) {
var fName = _getFullName(name);
if(!_isWatched(fName, object)) {
//Create new instance
Object.defineProperty(object, fName, {
enumerable: false,
configurable: true,
value: {}
});
}
return object[fName];
}
/**
* @description
* destroy/delete current watch instance
* @param name
* @param object
* @private
*/
function _destroy(name, object) {
return $$timeout(function() {
delete object[_getFullName(name)];
});
}
return {
$watch: _watch,
$destroy: _destroy
}
}];
});
/**
* @ngdoc module
* @name angular.filters
* @description
* Bunch of useful filters for angularJS
*/
angular.module('angular.filter', [
'a8m.ucfirst',
'a8m.uri-encode',
'a8m.slugify',
'a8m.strip-tags',
'a8m.stringular',
'a8m.truncate',
'a8m.starts-with',
'a8m.ends-with',
'a8m.wrap',
'a8m.trim',
'a8m.ltrim',
'a8m.rtrim',
'a8m.repeat',
'a8m.to-array',
'a8m.concat',
'a8m.contains',
'a8m.unique',
'a8m.is-empty',
'a8m.after',
'a8m.after-where',
'a8m.before',
'a8m.before-where',
'a8m.where',
'a8m.reverse',
'a8m.remove',
'a8m.remove-with',
'a8m.group-by',
'a8m.count-by',
'a8m.search-field',
'a8m.fuzzy-by',
'a8m.fuzzy',
'a8m.omit',
'a8m.pick',
'a8m.every',
'a8m.filter-by',
'a8m.xor',
'a8m.map',
'a8m.first',
'a8m.last',
'a8m.flatten',
'a8m.math',
'a8m.math.max',
'a8m.math.min',
'a8m.math.percent',
'a8m.math.radix',
'a8m.math.sum',
'a8m.math.degrees',
'a8m.math.radians',
'a8m.math.byteFmt',
'a8m.math.kbFmt',
'a8m.math.shortFmt',
'a8m.angular',
'a8m.conditions',
'a8m.is-null',
'a8m.filter-watcher'
]);
})( window, window.angular );