Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Krueger2015-05-07 07:18:26 -0400
committerJan Krueger2015-05-07 07:18:26 -0400
commit94ba614fb667a0ff778d2c85d9cb37581834baa0 (patch)
tree4b696c4d72edd206f25bd29f10f1f77e34db6ccd
parentb4e2b7c7b2006862d36d435eecea9de645026e78 (diff)
parent1c4d8b1b29762c637b4437cc831a8b93a646e24d (diff)
downloadorg.eclipse.openk-platform.openk-repo-94ba614fb667a0ff778d2c85d9cb37581834baa0.tar.gz
org.eclipse.openk-platform.openk-repo-94ba614fb667a0ff778d2c85d9cb37581834baa0.tar.xz
org.eclipse.openk-platform.openk-repo-94ba614fb667a0ff778d2c85d9cb37581834baa0.zip
Merge branch 'master' of ssh://git.eclipse.org/gitroot/openk-platform/org.eclipse.openk-platform.openk-repo
-rw-r--r--openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/controller/rest/ActivityRestController.java17
-rw-r--r--openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/model/process/Activity.java2
-rw-r--r--openk-platform/openk-eisman-portlet/src/main/webapp/js/app.js89
-rw-r--r--openk-platform/openk-eisman-portlet/src/main/webapp/jsp/details.jsp6
-rw-r--r--openk-platform/openk-eisman-portlet/src/main/webapp/jsp/overview.jsp6
-rw-r--r--openk-platform/openk-theme/src/main/webapp/css/additional.css16
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.css7
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.js3665
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.min.js2
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.css53
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.min.css2
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore-min.js6
-rw-r--r--openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore.js1564
-rw-r--r--openk-platform/openk-theme/src/main/webapp/templates/portal_normal.vm6
-rw-r--r--openk-platform/openk-theme/src/main/webapp/templates/portlet.vm4
15 files changed, 5349 insertions, 96 deletions
diff --git a/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/controller/rest/ActivityRestController.java b/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/controller/rest/ActivityRestController.java
index 28771761..dc0c7578 100644
--- a/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/controller/rest/ActivityRestController.java
+++ b/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/controller/rest/ActivityRestController.java
@@ -63,12 +63,12 @@ public class ActivityRestController {
}
- @RequestMapping(value = "/findDetailActivities", method = RequestMethod.GET)
+ @RequestMapping(value = "/findDetailActivitiyList", method = RequestMethod.GET)
public Page<Activity> findDetailActivities(final Pageable pageable,
@RequestParam(required = true) final String activityId,
@RequestParam(required = false) final String filter) {
LOG.info("calling REST - find Details for Activities");
-
+//TODO ID in URL auslagern
Specification<Activity> specification = null;
try {
@@ -84,11 +84,15 @@ public class ActivityRestController {
} catch (IOException e) {
LOG.error(e);
}
+ final Page<Activity> project = activityRepository.findAll(specification, pageable);
+
- return activityRepository.findAll(specification, pageable);
+ project.toString();
+
+ return project;
}
- @RequestMapping(value = "/findOverviewActivity", method = RequestMethod.GET)
+ @RequestMapping(value = "/findParentActivityList", method = RequestMethod.GET)
public Page<Activity> findActivity(final Pageable pageable,
@RequestParam(required = false) final String filter) {
LOG.info("calling REST - find Activity by params");
@@ -108,7 +112,10 @@ public class ActivityRestController {
LOG.error(e);
}
- return activityRepository.findAll(specification, pageable);
+ final Page<Activity> project = activityRepository.findAll(specification, pageable);
+
+ project.toString();
+ return project;
}
@JsonView(IncludeAttribute4Json.ParentActivity.class)
diff --git a/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/model/process/Activity.java b/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/model/process/Activity.java
index 196350fe..2bb94a83 100644
--- a/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/model/process/Activity.java
+++ b/openk-platform/openk-eisman-portlet/src/main/java/org/eclipse/openk/eisman/model/process/Activity.java
@@ -130,7 +130,7 @@ public class Activity extends AbstractBaseEntitiy {
private Preselection preselection;
@OneToMany(cascade = CascadeType.PERSIST)
- @JoinColumn(name = "ACTIVITY_ID", referencedColumnName = "ID")
+ @JoinColumn(name = "ACTIVITY_ID")
private List<Activity> activityList;
//
diff --git a/openk-platform/openk-eisman-portlet/src/main/webapp/js/app.js b/openk-platform/openk-eisman-portlet/src/main/webapp/js/app.js
index 224ee7d5..27e7b1bf 100644
--- a/openk-platform/openk-eisman-portlet/src/main/webapp/js/app.js
+++ b/openk-platform/openk-eisman-portlet/src/main/webapp/js/app.js
@@ -10,7 +10,7 @@
*******************************************************************************/
/* bootstrap and init => instead of using the tag ng-app */
//var app = angular.module('app', ['ngResource', 'ngGrid', 'angular-rickshaw'])
-var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.bootstrap', 'ngResource', 'ngRoute', 'ngAnimate', 'ui.grid.selection', 'ui.grid.pagination'])
+var app = angular.module('app', ['ngTouch', 'ui.grid', 'ngResource', 'ui.grid.selection', 'ui.grid.pagination', 'Mac'])
.run(function ($log) {
$log.info("App Module openK Eisman initiated");
}
@@ -23,56 +23,46 @@ var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.bootstrap', 'ngResour
app.directive('customPopover', function () {
return {
restrict: 'A',
- template: '<div><img style="display:{{display}}" src="/openk-theme/img/info.png"/>{{label}}</div>',
+ replace:true,
+ template:'<div><a class="btn btn-xs ng-scope" mac-popover-trigger="hover" mac-popover="tablePopover{{id}}" style="margin:5px;display:{{display}}" ><img src="/openk-theme/img/info.png"></a>'
+ + '{{station}}<mac-popover id="tablePopover{{id}}" ><div class="">'
+ + '<div class="panel panel-default" style="width:200px;"><div class="panel-heading"><h3 class="panel-title">{{title}}</h3></div><div class="panel-body">{{popoverHtml}}</div></div></div></mac-popover></div>',
link: function (scope, el, attrs) {
attrs.popoverTitle = 'Speisepunkte';
- var stations = (attrs.popoverLabel ? attrs.popoverLabel.split(';') : []);
+ var entry = (attrs.popoverLabel ? JSON.parse(attrs.popoverLabel) : []);
+ var stations = entry.substationList;
- var stationTemplate = '<div class="col-xs-12 col-sm-6 col-lg-3">' +
- '<div class="panel panel-default">' +
- ' <div class="panel-heading">' +
- '<h3 class="panel-title">Speisepunkte</h3>' +
- '</div>' +
- '<div class="panel-body">{{stations}}</div></div></div>';
+ scope.station = '';
+ scope.popoverHtml = '';
+ scope.title = 'Speisepunkte';
- var showPopover = false;
- if(stations.length <= 1){
- attrs.popoverHtml = '';
+ if(!stations || stations.length == 0){
+ scope.station = '';
scope.label = attrs.popoverLabel;
scope.display = 'none';
+ }else if (stations.length == 1) {
+ scope.station = stations[0].name;
+ scope.display = 'none';
}else{
- showPopover = true;
-
scope.display = 'inherit';
scope.label = '';
scope.stations = '';
+ scope.id = entry.id;
- stations.forEach(function(entry){
- scope.stations += entry;
- scope.stations += '</br>';
+ stations.forEach(function(station){
+ scope.stations += station.name;
+ scope.stations += ' ';
});
- attrs.popoverHtml = scope.stations;
- }
-
- if(showPopover){
- $(el).popover({
- trigger: 'hover',
- html: true,
- title: 'Speisepunkte',
- content: attrs.popoverHtml,
- placement: attrs.popoverPlacement
- });
+ scope.popoverHtml = scope.stations;
}
-
}
};
});
-
app.directive('loading', ['$http', '$timeout' ,function ($http, $timeout)
{
return {
@@ -109,7 +99,7 @@ app.filter('powerToBeReducedFilter', function () {
var val = '';
if(value){
- val = value.value + value.multiplier + value.unit;
+ val = value.value + ' ' + value.multiplier + value.unit;
}
return val;
};
@@ -135,7 +125,7 @@ app.filter('booleanFilter', function () {
Controller
*/
-app.controller('OverviewController', ['$scope', '$log', '$timeout','$http', '$location', '$route', function ($scope, $log, $timeout, $http, $location, $route){
+app.controller('OverviewController', ['$scope', '$log', '$timeout','$http', '$location', function ($scope, $log, $timeout, $http, $location){
$scope.navigateToDetails = function(entity){
@@ -147,8 +137,8 @@ app.controller('OverviewController', ['$scope', '$log', '$timeout','$http', '$lo
window.location.search += '?page=new';
}
- $scope.linkToDetailsTemplate = '<a class="btn btn-info btn-xs" ng-click="grid.appScope.navigateToDetails(row.entity)" >Details</a>';
- $scope.feederStationTemplate = '<div><span custom-popover popover-placement="bottom" popover-label="{{row.entity.feederStation}}"></span></div>';
+ $scope.linkToDetailsTemplate = '<a class="btn btn-info btn-xs" style="margin:5px;" ng-click="grid.appScope.navigateToDetails(row.entity)" >Details</a>';
+ $scope.feederStationTemplate = '<div><span custom-popover popover-placement="bottom" popover-label="{{row.entity}}"></span></div>';
$scope.searchOptions = {
pageNumber: 1,
@@ -170,13 +160,14 @@ app.controller('OverviewController', ['$scope', '$log', '$timeout','$http', '$lo
useExternalPagination: true,
useExternalSorting: true,
useExternalFiltering: true,
+ rowHeight:33,
columnDefs: [
{ name:'id', displayName:'ID', width: '10%'},
{ name:'dateStarted', displayName:'Von', cellFilter: "date:'dd.MM.yyyy hh:mm:ss'"},
{ name:'dateFinished', displayName:'Bis', cellFilter: "date:'dd.MM.yyyy hh:mm:ss'"},
- { name:'powerToBeReduced', displayName:'Abgeregelte Leistung', cellTemplate: '<div ng-bind="row.entity.powerToBeReduced | powerToBeReducedFilter"></div>'},
+ { name:'powerToBeReduced', displayName:'Abgeregelte Leistung', cellTemplate: '<div style="padding:5px;" ng-bind="row.entity.powerToBeReduced | powerToBeReducedFilter"></div>'},
{ name:'reasonOfReduction', displayName:'Begründung'},
- { name:'feederStation', displayName:'Speisepunkte',
+ { name:'substationList', displayName:'Speisepunkte',
cellTemplate: $scope.feederStationTemplate},
{ name:'practice', displayName:'Übung', enableFiltering:false, cellFilter:'booleanFilter'},
{ name:'details', displayName:'', width: 100, enableColumnMenu:false,
@@ -260,15 +251,11 @@ app.controller('OverviewController', ['$scope', '$log', '$timeout','$http', '$lo
params.filter = $scope.searchOptions.filter.filter;
}
- var config = {
- "method": "GET",
- "url": "/openk-eisman-portlet/rest/findOverviewActivity",
+ // Request absenden
+ $http.get("/openk-eisman-portlet/rest/findParentActivityList", {
"timeout": 30000,
"params": params
- };
-
- // Request absenden
- $http.get('/openk-eisman-portlet/rest/findOverviewActivity', config).success(function (data) {
+ }).success(function (data) {
$log.info("Success");
$scope.overview.data = data.content;
}).
@@ -327,16 +314,17 @@ app.controller('DetailController', ['$scope', '$log', '$timeout','$http', '$loca
enablePagingControls: true,
useExternalPagination: true,
useExternalSorting: true,
+ rowHeight:33,
useExternalFiltering: true,
columnDefs: [
{ name:'id', displayName:'ID', width: '10%'},
{ name:'dateStarted', displayName:'Von', cellFilter: "date:'dd.MM.yyyy hh:mm:ss'"},
{ name:'dateFinished', displayName:'Bis', cellFilter: "date:'dd.MM.yyyy hh:mm:ss'"},
- { name:'powerToBeReduced', displayName:'Abgeregelte Leistung', cellTemplate: '<div ng-bind="row.entity.powerToBeReduced | powerToBeReducedFilter"></div>'},
+ { name:'powerToBeReduced', displayName:'Abgeregelte Leistung', cellTemplate: '<div style="padding:5px;" ng-bind="row.entity.powerToBeReduced | powerToBeReducedFilter"></div>'},
{ name:'reasonOfReduction', displayName:'Begründung'},
{ name:'feederStation', displayName:'Speisepunkte',
enableFiltering:false, cellTemplate: $scope.feederStationTemplate},
- { name:'practice', displayName:'Übung', cellFilter:'booleanFilter'}
+ { name:'practice', displayName:'Übung', enableFiltering:false, cellFilter:'booleanFilter'}
],
onRegisterApi: function( gridApi ) {
$scope.gridApi = gridApi;
@@ -404,7 +392,6 @@ app.controller('DetailController', ['$scope', '$log', '$timeout','$http', '$loca
$scope.displayDetails = function(dataEntity){
-
var tmp = '';
//ID
@@ -480,15 +467,11 @@ app.controller('DetailController', ['$scope', '$log', '$timeout','$http', '$loca
params.activityId = $scope.getParam('activityId');
- var config = {
- "method": "GET",
- "url": "/openk-eisman-portlet/rest/findDetailActivities",
+ // Request absenden
+ $http.get("/openk-eisman-portlet/rest/findDetailActivitiyList", {
"timeout": 30000,
"params": params
- };
-
- // Request absenden
- $http.get('/openk-eisman-portlet/rest/findDetailActivities', config).success(function (data) {
+ }).success(function (data) {
$log.info("Success");
$scope.detail.data = data.content;
}).
diff --git a/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/details.jsp b/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/details.jsp
index 25d30b97..abb257d4 100644
--- a/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/details.jsp
+++ b/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/details.jsp
@@ -25,8 +25,10 @@
<h4 class="feature-heading"></h4>
</div>
- <div class="grid" ui-grid="detail" ui-grid-pagination ui-grid-selection></div>
- <div ng-bind-html="detailHTML" class="col-xs-12 col-sm-12" style="margin-top:20px;"></div>
+ <div class="col-sm-12">
+ <div class="grid table" ui-grid="detail" ui-grid-pagination ui-grid-selection></div>
+ </div>
+ <div ng-bind-html="detailHTML"></div>
<div class="col-xs-12 col-sm-12"><a class="btn btn-primary btn-sm" ng-click="navigateToCreate()" >Neue Massnahme</a></div>
</div>
</div> \ No newline at end of file
diff --git a/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/overview.jsp b/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/overview.jsp
index df53574b..1663cd0c 100644
--- a/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/overview.jsp
+++ b/openk-platform/openk-eisman-portlet/src/main/webapp/jsp/overview.jsp
@@ -24,9 +24,9 @@
<i class="fa fa-4x fa-certificate"></i>
<h4 class="feature-heading"></h4>
- </div>
- <div class="grid" ui-grid="overview" ui-grid-pagination ui-grid-resize-columns></div>
-
+ </div><div class="col-sm-12">
+ <div class="grid table" ui-grid="overview" ui-grid-pagination ui-grid-resize-columns></div>
+ </div>
<div class="col-xs-12 col-sm-12"><a class="btn btn-primary btn-sm" ng-click="navigateToCreate()" >Neuer Vorgang</a></div>
</div>
</div> \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/css/additional.css b/openk-platform/openk-theme/src/main/webapp/css/additional.css
index 228cd682..e6d1a3b4 100644
--- a/openk-platform/openk-theme/src/main/webapp/css/additional.css
+++ b/openk-platform/openk-theme/src/main/webapp/css/additional.css
@@ -37,4 +37,20 @@
background-repeat: no-repeat;
width:50px;
height:50px;
+}
+
+.mac-popover{
+ background:transparent!important;
+ border:none!important;
+ box-shadow:none!important;
+ padding-top:20px;
+}
+.mac-popover .tip{
+ display:none;
+}
+.ui-grid-header-cell .sortable{
+ height:60px!important;
+}
+.ui-grid-header-canvas{
+ background:white!important;
} \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.css b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.css
new file mode 100644
index 00000000..60a867b4
--- /dev/null
+++ b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.css
@@ -0,0 +1,7 @@
+.mac-date-time.ng-invalid-date,.mac-date-time.ng-invalid-time{background:#ffe2e2;border:solid 1px #dea9a9}.close,.close-modal{width:18px;height:18px;border-radius:9px;display:block;background:#bdc0c7;position:relative;opacity:1;}.close:after,.close-modal:after{content:'';display:block;width:2px;height:10px;background:#fff;position:absolute;top:4px;left:8px;transform:rotate(45deg)}.close:before,.close-modal:before{content:'';display:block;width:2px;height:10px;background:#fff;position:absolute;top:4px;left:8px;transform:rotate(-45deg)}.close:hover,.close-modal:hover{background:#828590}.hide{display:none}.affix{position:fixed;}.affix-bottom{position:absolute}
+.mac-menu{position:absolute;top:0;left:0;min-width:200px;background:#fff;box-shadow:0 3px 6px rgba(0,0,0,0.2);border:1px solid #d1d3d8;box-sizing:border-box;max-height:325px;overflow-y:auto;opacity:0;visibility:hidden;transition:opacity .1s ease-out,visibility .1s ease-out;z-index:4;}.mac-menu.visible{visibility:visible;opacity:1}.mac-menu ul{list-style:none;margin:0;padding-left:0;}.mac-menu ul .mac-menu-item{display:block;padding:5px 10px;transition:background .1s ease-out;color:#000;cursor:pointer;}.mac-menu ul .mac-menu-item.active{background:#e0e8fb;transition:0;text-decoration:none}
+.mac-modal-overlay{background-color:rgba(245,246,250,0.75);position:fixed;top:0;left:0;right:0;bottom:0;opacity:0;display:none;overflow-y:auto;z-index:3;}.mac-modal-overlay.ng-animate{display:block;transition:.2s ease-out all}.mac-modal-overlay.visible{opacity:1;display:block;}.mac-modal-overlay.visible .mac-modal{top:50%}.mac-modal{position:absolute;top:0;left:50%;width:500px;margin-left:-251px;background:#fff;border:1px solid #d1d3d8;box-shadow:0 4px 10px rgba(0,0,0,0.15);transition:top .2s ease-out;border-radius:3px;transform:rotateX(0) rotateY(0);}.mac-modal:after{content:"";display:block;position:absolute;bottom:-20px;height:20px;width:1px}.mac-close-modal{position:absolute;top:-5px;right:-5px;width:18px;height:18px;border-radius:9px;display:block;background:#bdc0c7;cursor:pointer;}.mac-close-modal:before,.mac-close-modal:after{content:'';display:block;width:2px;height:10px;background:#fff;position:absolute;top:4px;left:8px}.mac-close-modal:before{transform:rotate(-45deg)}.mac-close-modal:after{transform:rotate(45deg)}.mac-modal-content{padding:20px}
+.mac-popover{position:absolute;top:0;left:0;background:#fff;box-shadow:0 3px 6px rgba(0,0,0,0.2);border:1px solid #d1d3d8;box-sizing:border-box;transform:scale3d(0,0,0);opacity:0;transform-origin:left top;visibility:hidden;border-radius:3px;z-index:2;}.mac-popover.fixed{position:fixed}.mac-popover.visible{opacity:1;visibility:visible;transform:scale3d(1,1,1);transition:transform .1s ease-out,opacity .1s ease-in,visibility .1s ease-out}.mac-popover.ng-leave-active{opacity:0;transform:scale3d(0,0,0);visibility:hidden}.mac-popover .tip{display:block;width:0;height:0;border-bottom:9px solid #d1d3d8;border-left:9px solid rgba(255,255,255,0);border-right:9px solid rgba(255,255,255,0);position:absolute;top:-9px;left:15px;}.mac-popover .tip:after{content:'';display:block;width:0;height:0;border-bottom:8px solid #fff;border-left:8px solid rgba(255,255,255,0);border-right:8px solid rgba(255,255,255,0);position:absolute;top:1px;left:-8px}.mac-popover.above{transform-origin:left bottom;}.mac-popover.above .tip{top:auto;bottom:-9px;border-top:9px solid #d1d3d8;border-bottom:0;}.mac-popover.above .tip:after{top:auto;bottom:1px;border-top:8px solid #fff;border-bottom:0}.mac-popover.above.right{transform-origin:right bottom;}.mac-popover.above.right .tip{left:auto;right:15px}.mac-popover.below.right{transform-origin:right top;}.mac-popover.below.right .tip{left:auto;right:15px}.mac-popover.middle .tip{top:50%;margin-top:-9px;border-top:9px solid rgba(255,255,255,0);border-bottom:9px solid rgba(255,255,255,0);}.mac-popover.middle .tip:after{border-top:8px solid rgba(255,255,255,0);border-bottom:8px solid rgba(255,255,255,0);top:-8px}.mac-popover.middle.right{transform-origin:left center;}.mac-popover.middle.right .tip{border-left:0;border-right:9px solid #d1d3d8;left:-9px;}.mac-popover.middle.right .tip:after{border-left:0;border-right:8px solid #fff;left:1px}.mac-popover.middle.left{transform-origin:right center;}.mac-popover.middle.left .tip{border-right:0;border-left:9px solid #d1d3d8;right:-9px;left:auto;}.mac-popover.middle.left .tip:after{border-right:0;border-left:8px solid #fff;right:1px;left:auto}.mac-popover .popover-header{background:#eaecf1;display:none;}.mac-popover .popover-header .title{font-size:13px;font-weight:bold;line-height:33px;padding-left:10px;padding-top:1px;user-select:none;overflow:ellipsis;margin-right:40px}.mac-popover .popover-header .close{float:right;margin:7px 10px 0 0;display:none}.mac-popover .popover-content{max-height:415px;overflow-y:auto;overflow-x:hidden;position:relative}.mac-popover .popover-footer{display:none}.mac-popover.footer{padding-bottom:42px;}.mac-popover.footer .popover-footer{display:block;position:absolute;bottom:0;left:0;right:0;padding:10px;box-shadow:0 -1px 5px rgba(0,0,0,0.15)}.mac-popover.header .popover-header{display:block}.mac-popover.header.below .tip:after{border-bottom:8px solid #eaecf1}.mac-popover.header.middle.left .tip:after{border-left:8px solid #eaecf1}.mac-popover.header.middle.right .tip:after{border-right:8px solid #eaecf1}
+.mac-spinner,.mac-cspinner{display:inline-block;position:relative;}.mac-spinner.block,.mac-cspinner.block{display:block;margin:0 auto}@-moz-keyframes fade{0%{opacity:1}100%{opacity:.02}}@-webkit-keyframes fade{0%{opacity:1}100%{opacity:.02}}@-o-keyframes fade{0%{opacity:1}100%{opacity:.02}}@keyframes fade{0%{opacity:1}100%{opacity:.02}}
+.mac-tag-autocomplete{position:relative;display:inline-block;border:1px solid #aaa;background:#fff;margin:0;padding:0;}.mac-tag-autocomplete .mac-tag-list{margin:0;padding-left:0;}.mac-tag-autocomplete .mac-tag-list .mac-tag{padding:3px 20px 3px 5px;margin:3px;position:relative;display:inline-block;list-style:none;font-size:13px;line-height:13px;border-radius:3px;}.mac-tag-autocomplete .mac-tag-list .mac-tag.mac-label{background:linear-gradient(top,#eaf0ff,#dee8ff);border:1px solid #bfc9e1;text-shadow:none;color:#000;font-weight:normal;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,0.05)}.mac-tag-autocomplete .mac-tag-list .mac-tag .mac-tag-close{position:absolute;right:6px;color:#9da6b7;cursor:pointer}.mac-tag-autocomplete .mac-tag-list .mac-tag.mac-input-tag{white-space:nowrap;padding:0;}.mac-tag-autocomplete .mac-tag-list .mac-tag.mac-input-tag .text-input{color:#666;background:transparent;padding:5px;margin:0;border:none !important;box-shadow:none}.mac-tag-autocomplete .mac-tag-list .mac-tag.mac-input-tag.fullwidth{width:100%;}.mac-tag-autocomplete .mac-tag-list .mac-tag.mac-input-tag.fullwidth .text-input{width:90%}
+.mac-tooltip{background:rgba(47,48,53,0.75);text-align:center;color:#fff;padding:5px 7px;position:absolute;top:100px;left:100px;font-size:12px;opacity:0;visibility:hidden;transition:opacity .1s ease-out,visibility .1s ease-out,margin .1s ease-out;margin-top:5px;border-radius:3px;z-index:7;}.mac-tooltip.visible{visibility:visible;opacity:1;margin-top:0}.mac-tooltip:after{content:'';display:block;width:0;height:0;position:absolute}.mac-tooltip.top:after{border-top:6px solid rgba(47,48,53,0.75);border-left:6px solid transparent;border-right:6px solid transparent;bottom:-6px;left:50%;margin-left:-6px}.mac-tooltip.bottom:after{border-bottom:6px solid rgba(47,48,53,0.75);border-left:6px solid transparent;border-right:6px solid transparent;top:-6px;left:50%;margin-left:-6px}.mac-tooltip.left:after{border-left:6px solid rgba(47,48,53,0.75);border-top:6px solid transparent;border-bottom:6px solid transparent;right:-6px;top:50%;margin-top:-6px}.mac-tooltip.right:after{border-right:6px solid rgba(47,48,53,0.75);border-top:6px solid transparent;border-bottom:6px solid transparent;left:-6px;top:50%;margin-top:-6px} \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.js b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.js
new file mode 100644
index 00000000..aed758db
--- /dev/null
+++ b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.js
@@ -0,0 +1,3665 @@
+/**
+ * MacGyver v0.6.1
+ * @link http://angular-macgyver.github.io/MacGyver
+ * @license MIT
+ */
+(function(window, angular, undefined) {
+var augmentWidthOrHeight, core_pnum, cssExpand, extendjQuery, getStyles, getWidthOrHeight, getWindow, isScope, isWindow, jqLiteExtend, modules, rnumnonpx;
+
+modules = ["Mac.Util"];
+
+try {
+ angular.module("ngAnimate");
+ modules.push("ngAnimate");
+} catch (_error) {}
+
+angular.module("Mac", modules);
+
+
+/*
+@chalk overview
+@name angular.element
+
+@description
+Angular comes with jqLite, a tiny, API-compatible subset of jQuery. However, its
+functionality is very limited and MacGyver extends jqLite to make sure MacGyver
+components work properly.
+
+Real jQuery will continue to take precedence over jqLite and all functions MacGyver extends.
+
+MacGyver adds the following methods:
+- [height()](http://api.jquery.com/height/) - Does not support set
+- [width()](http://api.jquery.com/width/) - Does not support set
+- [outerHeight()](http://api.jquery.com/outerHeight/) - Does not support set
+- [outerWidth()](http://api.jquery.com/outerWidth/) - Does not support set
+- [offset()](http://api.jquery.com/offset/)
+- [scrollTop()](http://api.jquery.com/scrollTop/)
+ */
+
+cssExpand = ["Top", "Right", "Bottom", "Left"];
+
+core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source;
+
+rnumnonpx = new RegExp("^(" + core_pnum + ")(?!px)[a-z%]+$", "i");
+
+getStyles = function(element) {
+ return window.getComputedStyle(element, null);
+};
+
+isWindow = function(obj) {
+ return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+};
+
+isScope = function(obj) {
+ return obj && (obj.$evalAsync != null) && (obj.$watch != null);
+};
+
+angular.isScope = isScope;
+
+getWindow = function(element) {
+ if (isWindow(element)) {
+ return element;
+ } else {
+ return element.nodeType === 9 && element.defaultView;
+ }
+};
+
+augmentWidthOrHeight = function(element, name, extra, isBorderBox, styles) {
+ var i, start, val, _i;
+ if (extra === (isBorderBox ? "border" : "content")) {
+ return 0;
+ }
+ val = 0;
+ start = name === "Width" ? 1 : 0;
+ for (i = _i = start; _i <= 3; i = _i += 2) {
+ if (extra === "margin") {
+ val += parseFloat(styles["" + extra + cssExpand[i]]);
+ }
+ if (isBorderBox) {
+ if (extra === "content") {
+ val -= parseFloat(styles["padding" + cssExpand[i]]);
+ }
+ if (extra !== "margin") {
+ val -= parseFloat(styles["border" + cssExpand[i]]);
+ }
+ } else {
+ val += parseFloat(styles["padding" + cssExpand[i]]);
+ if (extra !== "padding") {
+ val += parseFloat(styles["border" + cssExpand + "Width"]);
+ }
+ }
+ }
+ return val;
+};
+
+getWidthOrHeight = function(type, prefix, element) {
+ return function(margin) {
+ var defaultExtra, doc, extra, isBorderBox, name, styles, value, valueIsBorderBox;
+ defaultExtra = (function() {
+ switch (prefix) {
+ case "inner":
+ return "padding";
+ case "outer":
+ return "";
+ default:
+ return "content";
+ }
+ })();
+ extra = defaultExtra || (margin === true ? "margin" : "border");
+ if (isWindow(element)) {
+ return element.document.documentElement["client" + type];
+ }
+ if (element.nodeType === 9) {
+ doc = element.documentElement;
+ return Math.max(element.body["scroll" + type], doc["scroll" + type], element.body["offset" + type], doc["offset" + type], doc["client" + type]);
+ }
+ valueIsBorderBox = true;
+ styles = getStyles(element);
+ name = type.toLowerCase();
+ value = type === "Height" ? element.offsetHeight : element.offsetWidth;
+ isBorderBox = element.style.boxSizing === "border-box";
+ if (value <= 0 || value === null) {
+ value = styles[name];
+ if (value < 0 || value === null) {
+ value = element.style[name];
+ }
+ if (rnumnonpx.test(value)) {
+ return value;
+ }
+ valueIsBorderBox = isBorderBox;
+ value = parseFloat(value) || 0;
+ }
+ return value + augmentWidthOrHeight(element, type, extra || (isBorderBox ? "border" : "content"), valueIsBorderBox, styles);
+ };
+};
+
+jqLiteExtend = {
+ height: function(element) {
+ return getWidthOrHeight("Height", "", element)();
+ },
+ width: function(element) {
+ return getWidthOrHeight("Width", "", element)();
+ },
+ outerHeight: function(element, margin) {
+ return getWidthOrHeight("Height", "outer", element)(margin);
+ },
+ outerWidth: function(element, margin) {
+ return getWidthOrHeight("Width", "outer", element)(margin);
+ },
+ offset: function(element) {
+ var box, doc, docElem, win;
+ box = {
+ top: 0,
+ left: 0
+ };
+ doc = element && element.ownerDocument;
+ if (!doc) {
+ return;
+ }
+ docElem = doc.documentElement;
+ if (element.getBoundingClientRect != null) {
+ box = element.getBoundingClientRect();
+ }
+ win = getWindow(doc);
+ return {
+ top: box.top + win.pageYOffset - docElem.clientTop,
+ left: box.left + win.pageXOffset - docElem.clientLeft
+ };
+ },
+ scrollTop: function(element, value) {
+ var win;
+ win = getWindow(element);
+ if (value == null) {
+ if (win) {
+ return win["pageYOffset"];
+ } else {
+ return element["scrollTop"];
+ }
+ }
+ if (win) {
+ return win.scrollTo(window.pageYOffset, value);
+ } else {
+ return element["scrollTop"] = value;
+ }
+ },
+ scrollLeft: function(element, value) {
+ var win;
+ win = getWindow(element);
+ if (value == null) {
+ if (win) {
+ return win["pageXOffset"];
+ } else {
+ return element["scrollLeft"];
+ }
+ }
+ if (win) {
+ return win.scrollTo(window.pageXOffset, value);
+ } else {
+ return element["scrollLeft"] = value;
+ }
+ }
+};
+
+extendjQuery = function() {
+ var jqLite;
+ if ((window.jQuery != null) && (angular.element.prototype.offset != null)) {
+ return;
+ }
+ jqLite = angular.element;
+ return angular.forEach(jqLiteExtend, function(fn, name) {
+ return jqLite.prototype[name] = function(arg1, arg2) {
+ if (this.length) {
+ return fn(this[0], arg1, arg2);
+ }
+ };
+ });
+};
+
+extendjQuery();
+
+
+/*
+@chalk overview
+@name mac-affix
+
+@description
+Fix the component at a certain position
+
+@param {Expr} mac-affix-disabled To unpin element (default false)
+@param {Expr} mac-affix-top Top offset (default 0)
+@param {Expr} mac-affix-bottom Bottom offset (default 0)
+@param {Event} refresh-mac-affix To update the position of affixed element
+ */
+angular.module("Mac").directive("macAffix", [
+ "$document", "$window", function($document, $window) {
+ return {
+ link: function($scope, element, attrs) {
+ var defaults, disabled, getPinnedOffset, lastAffix, offset, pinnedOffset, scrollEvent, setOffset, unpin, windowEl;
+ defaults = {
+ top: 0,
+ bottom: 0,
+ disabled: false,
+ classes: "affix affix-top affix-bottom"
+ };
+ offset = {
+ top: defaults.top,
+ bottom: defaults.bottom
+ };
+ disabled = defaults.disabled;
+ lastAffix = null;
+ unpin = null;
+ pinnedOffset = null;
+ windowEl = angular.element($window);
+
+ /*
+ @name setOffset
+ @description
+ Update top or bottom offset. This function will make sure the value is
+ an integer and use default value
+ @param {String} key Offset key
+ @param {String|Integer} value Update value
+ @param {Bool} useDefault
+ */
+ setOffset = function(key, value, useDefault) {
+ if (useDefault == null) {
+ useDefault = false;
+ }
+ if (useDefault && (value == null)) {
+ value = defaults[key];
+ }
+ if ((value != null) && !isNaN(+value)) {
+ return offset[key] = +value;
+ }
+ };
+ if (attrs.macAffixTop != null) {
+ setOffset("top", $scope.$eval(attrs.macAffixTop), true);
+ $scope.$watch(attrs.macAffixTop, function(value) {
+ return setOffset("top", value);
+ });
+ }
+ if (attrs.macAffixBottom != null) {
+ setOffset("bottom", $scope.$eval(attrs.macAffixBottom), true);
+ $scope.$watch(attrs.macAffixBottom, function(value) {
+ return setOffset("bottom", value);
+ });
+ }
+ getPinnedOffset = function() {
+ var scrollHeight;
+ if (pinnedOffset != null) {
+ return pinnedOffset;
+ }
+ element.removeClass(defaults.classes).addClass("affix");
+ scrollHeight = $document.height();
+ pinnedOffset = scrollHeight - element.outerHeight() - offset.bottom;
+ return pinnedOffset;
+ };
+ scrollEvent = function() {
+ var affix, curOffset, elementHeight, position, scrollHeight, scrollTop;
+ if (element[0].offsetHeight <= 0 && element[0].offsetWidth <= 0) {
+ return;
+ }
+ position = element.offset();
+ scrollTop = windowEl.scrollTop();
+ scrollHeight = $document.height();
+ elementHeight = element.outerHeight();
+ affix = (unpin != null) && scrollTop <= unpin ? false : (offset.bottom != null) && scrollTop > scrollHeight - elementHeight - offset.bottom ? "bottom" : (offset.top != null) && scrollTop <= offset.top ? "top" : false;
+ if (affix === lastAffix) {
+ return;
+ }
+ if (unpin) {
+ element.css("top", "");
+ }
+ lastAffix = affix;
+ unpin = affix === "bottom" ? getPinnedOffset() : null;
+ element.removeClass(defaults.classes).addClass("affix" + (affix ? "-" + affix : ""));
+ if (affix === "bottom") {
+ curOffset = element.offset();
+ element.css("top", unpin - curOffset.top);
+ }
+ return true;
+ };
+ if (attrs.macAffixDisabled != null) {
+ disabled = $scope.$eval(attrs.macAffixDisabled) || defaults.disabled;
+ $scope.$watch(attrs.macAffixDisabled, function(value) {
+ var action;
+ if ((value == null) || value === disabled) {
+ return;
+ }
+ disabled = value;
+ action = value ? "unbind" : "bind";
+ windowEl[action]("scroll", scrollEvent);
+ if (disabled) {
+ lastAffix = null;
+ unpin = null;
+ return element.css("top", "").removeClass(defaults.classes);
+ } else {
+ return scrollEvent();
+ }
+ });
+ }
+ if (!disabled) {
+ windowEl.bind("scroll", scrollEvent);
+ }
+ $scope.$on("refresh-mac-affix", function() {
+ var position;
+ return position = element.offset();
+ });
+ return $scope.$on("$destroy", function() {
+ return windowEl.unbind("scroll", scrollEvent);
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Autocomplete
+
+@description
+A directive for providing suggestions while typing into the field
+
+Autocomplete allows for custom html templating in the dropdown and some properties are exposed on the local scope on each template instance, including:
+
+| Variable | Type | Details |
+|-----------|---------|-----------------------------------------------------------------------------|
+| `$index` | Number | iterator offset of the repeated element (0..length-1) |
+| `$first` | Boolean | true if the repeated element is first in the iterator. |
+| `$middle` | Boolean | true if the repeated element is between the first and last in the iterator. |
+| `$last` | Boolean | true if the repeated element is last in the iterator. |
+| `$even` | Boolean | true if the iterator position `$index` is even (otherwise false). |
+| `$odd` | Boolean | true if the iterator position `$index` is odd (otherwise false). |
+| `item` | Object | item object with `value` and `label` if label-key is set |
+
+To use custom templating
+
+```
+<mac-autocomplete mac-autocomplete-url="someUrl" ng-model="model">
+ <span> {{item.label}} </span>
+</mac-autocomplete>
+```
+
+Template default to `{{item.label}}` if not defined
+
+@dependencies
+- mac-menu
+
+@param {String} ng-model Assignable angular expression to data-bind to (required)
+@param {String} mac-placeholder Placeholder text
+@param {String} mac-autocomplete-url Url to fetch autocomplete dropdown list data. URL may include GET params e.g. "/users?nocache=1"
+@param {Expression} mac-autocomplete-source Data to use.
+Source support multiple types:
+- Array: An array can be used for local data and there are two supported formats:
+ - An array of strings: ["Item1", "Item2"]
+ - An array of objects with mac-autocomplete-label key: [{name:"Item1"}, {name:"Item2"}]
+- String: Using a string as the source is the same as passing the variable into mac-autocomplete-url
+- Function: A callback when querying for data. The callback receive two arguments:
+ - {String} Value currently in the text input
+ - {Function} A response callback which expects a single argument, data to user. The data will be
+ populated on the menu and the menu will adjust accordingly
+@param {Boolean} mac-autocomplete-disabled Boolean value if autocomplete should be disabled
+@param {Function} mac-autocomplete-on-select Function called when user select on an item
+- `selected` - {Object} The item selected
+@param {Function} mac-autocomplete-on-success function called on success ajax request
+- `data` - {Object} Data returned from the request
+- `status` - {Number} The status code of the response
+- `header` - {Object} Header of the response
+@param {Function} mac-autocomplete-on-error Function called on ajax request error
+- `data` - {Object} Data returned from the request
+- `status` - {Number} The status code of the response
+- `header` - {Object} Header of the response
+@param {String} mac-autocomplete-label The label to display to the users (default "name")
+@param {String} mac-autocomplete-query The query parameter on GET command (default "q")
+@param {Integer} mac-autocomplete-delay Delay on fetching autocomplete data after keyup (default 800)
+
+@param {Expr} mac-menu-class Classes for mac-menu used by mac-autocomplete. For more info, check [ngClass](http://docs.angularjs.org/api/ng/directive/ngClass)
+ */
+angular.module("Mac").directive("macAutocomplete", [
+ "$animate", "$compile", "$filter", "$http", "$parse", "$rootScope", "$timeout", "keys", function($animate, $compile, $filter, $http, $parse, $rootScope, $timeout, keys) {
+ return {
+ restrict: "EA",
+ template: "<input type=\"text\">",
+ transclude: true,
+ replace: true,
+ require: "ngModel",
+ link: function($scope, element, attrs, ctrl, transclude) {
+ var $menuScope, appendMenu, autocompleteUrl, blurHandler, currentAutocomplete, delay, disabled, getData, inside, isMenuAppended, labelGetter, labelKey, menuEl, onError, onSelect, onSuccess, positionMenu, preventParser, queryData, queryKey, reset, source, timeoutId, updateItem;
+ labelKey = attrs.macAutocompleteLabel || "name";
+ labelGetter = $parse(labelKey);
+ queryKey = attrs.macAutocompleteQuery || "q";
+ delay = +(attrs.macAutocompleteDelay || 800);
+ inside = attrs.macAutocompleteInside != null;
+ autocompleteUrl = $parse(attrs.macAutocompleteUrl);
+ onSelect = $parse(attrs.macAutocompleteOnSelect);
+ onSuccess = $parse(attrs.macAutocompleteOnSuccess);
+ onError = $parse(attrs.macAutocompleteOnError);
+ source = $parse(attrs.macAutocompleteSource);
+ disabled = $parse(attrs.macAutocompleteDisabled);
+ currentAutocomplete = [];
+ timeoutId = null;
+ isMenuAppended = false;
+ preventParser = false;
+ $menuScope = $scope.$new();
+ $menuScope.items = [];
+ $menuScope.index = 0;
+ $menuScope.select = function(index) {
+ var label, selected;
+ selected = currentAutocomplete[index];
+ onSelect($scope, {
+ selected: selected
+ });
+ label = $menuScope.items[index].label || "";
+ preventParser = true;
+ if (attrs.ngModel != null) {
+ ctrl.$setViewValue(label);
+ ctrl.$render();
+ }
+ return reset();
+ };
+ menuEl = angular.element(document.createElement("mac-menu"));
+ menuEl.attr({
+ "ng-class": attrs.macMenuClass || "",
+ "mac-menu-items": "items",
+ "mac-menu-select": "select(index)",
+ "mac-menu-index": "index"
+ });
+ transclude($menuScope, function(clone) {
+ return menuEl.append(clone);
+ });
+ $compile(menuEl)($menuScope);
+ ctrl.$parsers.push(function(value) {
+ if (value && !disabled($scope) && !preventParser) {
+ if (timeoutId != null) {
+ $timeout.cancel(timeoutId);
+ }
+ if (delay > 0) {
+ timeoutId = $timeout(function() {
+ return queryData(value);
+ }, delay);
+ } else {
+ queryData(value);
+ }
+ } else {
+ reset();
+ }
+ preventParser = false;
+ return value;
+ });
+
+ /*
+ @name blurHandler
+ @description
+ Create a blur handler function to make sure directive is unbinding
+ the correct handler
+ */
+ blurHandler = function() {
+ return $scope.$apply(function() {
+ return reset();
+ });
+ };
+
+ /*
+ @function
+ @name appendMenu
+ @description
+ Adding menu to DOM
+ @param {Function} callback Callback after enter animation completes
+ @returns {Promise} Animation promise
+ */
+ appendMenu = function() {
+ if (!isMenuAppended) {
+ element.bind("blur", blurHandler);
+ menuEl.on('mousedown', function(event) {
+ return event.preventDefault();
+ });
+ }
+ isMenuAppended = true;
+ menuEl[0].style.visibility = 'hidden';
+ if (inside) {
+ return $animate.enter(menuEl, void 0, element);
+ } else {
+ return $animate.enter(menuEl, angular.element(document.body));
+ }
+ };
+
+ /*
+ @function
+ @name reset
+ @description
+ Resetting autocomplete
+ @returns {Promise} Leave animation promise
+ */
+ reset = function() {
+ return $animate.leave(menuEl).then(function() {
+ $menuScope.index = 0;
+ $menuScope.items.length = 0;
+ menuEl[0].style.top = "";
+ menuEl[0].style.left = "";
+ isMenuAppended = false;
+ return element.unbind("blur", blurHandler);
+ });
+ };
+
+ /*
+ @function
+ @name positionMenu
+ @description
+ Calculate the style include position and width for menu
+ */
+ positionMenu = function() {
+ var offset;
+ offset = element.offset();
+ offset.top += element.outerHeight();
+ offset.minWidth = element.outerWidth();
+ angular.forEach(offset, function(value, key) {
+ if (!isNaN(+value) && angular.isNumber(+value)) {
+ value = "" + value + "px";
+ }
+ return menuEl[0].style[key] = value;
+ });
+ return menuEl[0].style.visibility = 'visible';
+ };
+
+ /*
+ @function
+ @name updateItem
+ @description
+ Update list of items getting passed to menu
+ @param {Array} data Array of data
+ */
+ updateItem = function(data) {
+ if ((data != null ? data.length : void 0) > 0) {
+ currentAutocomplete = data;
+ $menuScope.items = data.map(function(item) {
+ if (angular.isObject(item)) {
+ if (item.value == null) {
+ item.value = labelGetter(item) || "";
+ }
+ if (item.label == null) {
+ item.label = labelGetter(item) || "";
+ }
+ return item;
+ } else {
+ return {
+ label: item,
+ value: item
+ };
+ }
+ });
+ return appendMenu().then(positionMenu);
+ } else {
+ return reset();
+ }
+ };
+
+ /*
+ @function
+ @name getData
+ @description
+ GET request to fetch data from server, update menu items and position
+ menu
+ @param {String} url URL to fetch data from
+ */
+ getData = function(url, query) {
+ var options;
+ options = {
+ method: "GET",
+ url: url,
+ params: {}
+ };
+ options.params[queryKey] = query;
+ return $http(options).success(function(data, status, headers, config) {
+ var dataList;
+ dataList = onSuccess($scope, {
+ data: data,
+ status: status,
+ headers: headers
+ });
+ if (dataList == null) {
+ dataList = data.data;
+ }
+ return updateItem(dataList);
+ }).error(function(data, status, headers, config) {
+ return onError($scope, {
+ data: data,
+ status: status,
+ headers: headers
+ });
+ });
+ };
+
+ /*
+ @function
+ @name queryData
+ @description
+ Used for querying data
+ @param {String} query Search query
+ */
+ queryData = function(query) {
+ var sourceData, url;
+ url = autocompleteUrl($scope);
+ if (url) {
+ return getData(url, query);
+ } else {
+ sourceData = source($scope);
+ if (angular.isArray(sourceData)) {
+ return updateItem($filter("filter")(sourceData, query));
+ } else if (angular.isString(sourceData)) {
+ return getData(sourceData, query);
+ } else if (angular.isFunction(sourceData)) {
+ return sourceData(query, updateItem);
+ }
+ }
+ };
+ element.bind("keydown", function(event) {
+ if ($menuScope.items.length === 0) {
+ return true;
+ }
+ switch (event.which) {
+ case keys.DOWN:
+ $scope.$apply(function() {
+ $menuScope.index = ($menuScope.index + 1) % $menuScope.items.length;
+ return event.preventDefault();
+ });
+ break;
+ case keys.UP:
+ $scope.$apply(function() {
+ $menuScope.index = ($menuScope.index ? $menuScope.index : $menuScope.items.length) - 1;
+ return event.preventDefault();
+ });
+ break;
+ case keys.ENTER:
+ $scope.$apply(function() {
+ $menuScope.select($menuScope.index);
+ return event.preventDefault();
+ });
+ break;
+ case keys.ESCAPE:
+ $scope.$apply(function() {
+ reset();
+ return event.preventDefault();
+ });
+ }
+ return true;
+ });
+ $scope.$on("$destroy", function() {
+ $menuScope.$destroy();
+ return reset();
+ });
+
+ /*
+ @event
+ @name reset-mac-autocomplete
+ @description
+ Event to reset autocomplete
+ */
+ return $scope.$on("reset-mac-autocomplete", function() {
+ return reset();
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Canvas Spinner
+
+@description
+A directive for generating a canvas spinner
+This spinner requires much less CPU/GPU resources than CSS spinner
+
+@param {Integer} mac-cspinner-width Width of each bar (default 2)
+@param {Integer} mac-cspinner-height Height of each bar (default 5)
+@param {Integer} mac-cpsinner-border Border radius (default 1)
+@param {Integer} mac-cspinner-size Dimension of the whole spinner excluding padding (default 20)
+@param {Integer} mac-cspinner-radius Center radius (default 4)
+@param {Integer} mac-cspinner-bars Number of bars (default 10)
+@param {Integer} mac-cspinner-padding Padding around the spinner (default 3)
+@param {Integer} mac-cspinner-speed ms delay between each animation
+@param {String} mac-cspinner-color Color of each bar
+@param {Expr} mac-cspinner-spin Start or stop spinner
+ */
+angular.module("Mac").directive("macCspinner", [
+ "$timeout", "util", function($timeout, util) {
+ return {
+ restrict: "E",
+ replace: "true",
+ template: "<div class=\"mac-cspinner\"></div>",
+ compile: function(element, attrs) {
+ var canvas, canvasRadius, ctx, defaults, height, i, left, maxCanvasRadius, maxRadius, opacity, opts, prop, radius, ratio, rgb, rotation, showCtx, size, templateCanvas, top, width, _i, _j, _len, _ref, _ref1;
+ if (!window.HTMLCanvasElement) {
+ return console.log("Browser does not support canvas");
+ }
+ defaults = {
+ width: 2,
+ height: 5,
+ border: 1,
+ radius: 4,
+ bars: 10,
+ padding: 3,
+ speed: 100,
+ color: "#2f3035",
+ size: 20
+ };
+ opts = util.extendAttributes("macCspinner", defaults, attrs);
+ if (attrs.macCspinnerSize != null) {
+ size = !isNaN(+attrs.macCspinnerSize) && +attrs.macCspinnerSize;
+ if (size) {
+ ratio = size / defaults.size;
+ _ref = ["width", "height", "border", "radius"];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ prop = _ref[_i];
+ opts[prop] = defaults[prop] * ratio;
+ }
+ }
+ }
+ width = opts.width;
+ height = opts.height;
+ radius = opts.border;
+ maxRadius = opts.radius + height;
+ maxCanvasRadius = Math.max(width, maxRadius);
+ canvasRadius = Math.ceil(Math.max(maxCanvasRadius, util.pyth(maxRadius, width / 2)));
+ canvasRadius += opts.padding;
+ templateCanvas = angular.element("<canvas></canvas>");
+ ctx = templateCanvas[0].getContext("2d");
+ rotation = util.radian(360 / opts.bars);
+ ctx.translate(canvasRadius, canvasRadius);
+ top = -maxRadius;
+ left = -width / 2;
+ rgb = util.hex2rgb(opts.color);
+ for (i = _j = 0, _ref1 = opts.bars - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
+ opacity = 1 - (0.8 / opts.bars) * i;
+ ctx.fillStyle = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + opacity + ")";
+ ctx.beginPath();
+ ctx.moveTo(left + radius, top);
+ ctx.arc(left + width - radius, top + radius, radius, util.radian(-90), util.radian(0), false);
+ ctx.arc(left + width - radius, top + height - radius, radius, util.radian(0), util.radian(90), false);
+ ctx.arc(left + radius, top + height - radius, radius, util.radian(90), util.radian(180), false);
+ ctx.arc(left + radius, top + radius, radius, util.radian(-180), util.radian(-90), false);
+ ctx.closePath();
+ ctx.fill();
+ ctx.rotate(rotation);
+ }
+ canvas = angular.element("<canvas></canvas>");
+ canvas.attr({
+ width: canvasRadius * 2,
+ height: canvasRadius * 2
+ });
+ showCtx = canvas[0].getContext("2d");
+ showCtx.translate(canvasRadius, canvasRadius);
+ element.append(canvas);
+ return function($scope, element, attrs) {
+ var intervalID, spinning, start, stop;
+ intervalID = null;
+ spinning = false;
+ stop = function() {
+ spinning = false;
+ if (intervalID != null) {
+ return $timeout.cancel(intervalID);
+ }
+ };
+ start = function() {
+ var drawFn, rotate;
+ if (spinning) {
+ return;
+ }
+ spinning = true;
+ rotate = util.radian(360 / opts.bars);
+ return (drawFn = function(startCycle) {
+ if (startCycle == null) {
+ startCycle = false;
+ }
+ showCtx.clearRect(-canvasRadius, -canvasRadius, canvasRadius * 2, canvasRadius * 2);
+ showCtx.rotate(rotate);
+ showCtx.drawImage(templateCanvas[0], -canvasRadius, -canvasRadius);
+ if (spinning) {
+ if (!startCycle && element[0].offsetHeight <= 0 && element[0].offsetWidth <= 0) {
+ return stop();
+ }
+ return intervalID = $timeout(drawFn, opts.speed, false);
+ }
+ })(true);
+ };
+ if (attrs.macCspinnerSpin != null) {
+ $scope.$watch(attrs.macCspinnerSpin, function(value) {
+ if (value && !spinning) {
+ return start();
+ } else {
+ return stop();
+ }
+ });
+ } else {
+ start();
+ }
+ if (attrs.ngShow) {
+ $scope.$watch(attrs.ngShow, function(value) {
+ if (value) {
+ return start();
+ } else {
+ return stop();
+ }
+ });
+ } else if (attrs.ngHide) {
+ $scope.$watch(attrs.ngHide, function(value) {
+ if (value) {
+ return stop();
+ } else {
+ return start();
+ }
+ });
+ }
+ return $scope.$on("$destroy", function() {
+ return stop();
+ });
+ };
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Keydown events
+
+@description
+A directive for handling certain keys on keydown event
+Currently MacGyver supports enter, escape, space, left, up, right and down
+
+@param {Expression} mac-keydown-enter Expression to evaluate on hitting enter
+@param {Expression} mac-keydown-escape Expression to evaluate on hitting escape
+@param {Expression} mac-keydown-space Expression to evaluate on hitting space
+@param {Expression} mac-keydown-left Expression to evaluate on hitting left
+@param {Expression} mac-keydown-up Expression to evaluate on hitting up
+@param {Expression} mac-keydown-right Expression to evaluate on hitting right
+@param {Expression} mac-keydown-down Expression to evaluate on hitting down
+ */
+var key, _fn, _i, _len, _ref;
+
+_ref = ["Enter", "Escape", "Space", "Left", "Up", "Right", "Down"];
+_fn = function(key) {
+ return angular.module("Mac").directive("macKeydown" + key, [
+ "$parse", "keys", function($parse, keys) {
+ return {
+ restrict: "A",
+ link: function(scope, element, attributes) {
+ var expression;
+ expression = $parse(attributes["macKeydown" + key]);
+ return element.bind("keydown", function($event) {
+ if ($event.which === keys["" + (key.toUpperCase())]) {
+ $event.preventDefault();
+ return scope.$apply(function() {
+ return expression(scope, {
+ $event: $event
+ });
+ });
+ }
+ });
+ }
+ };
+ }
+ ]);
+};
+for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ _fn(key);
+}
+
+
+/*
+@chalk overview
+@name Pause Typing
+
+@description
+macPauseTyping directive allow user to specify custom behavior after user stops typing for more than (delay) milliseconds
+
+@param {Expression} mac-pause-typing Expression to evaluate after delay
+@param {Expression} mac-pause-typing-delay Delay value to evaluate expression (default 800)
+ */
+angular.module("Mac").directive("macPauseTyping", [
+ "$parse", "$timeout", function($parse, $timeout) {
+ return {
+ restrict: "A",
+ link: function(scope, element, attributes) {
+ var delay, expression, keyupTimer;
+ expression = $parse(attributes["macPauseTyping"]);
+ delay = scope.$eval(attributes["macPauseTypingDelay"]) || 800;
+ keyupTimer = null;
+ return element.bind("keyup", function($event) {
+ if (keyupTimer != null) {
+ $timeout.cancel(keyupTimer);
+ }
+ return keyupTimer = $timeout(function() {
+ return expression(scope, {
+ $event: $event
+ });
+ }, delay);
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Windows Resize
+
+@description
+Binding custom behavior on window resize event
+
+@param {Expression} mac-window-resize Expression to evaluate on window resize
+ */
+angular.module("Mac").directive("macWindowResize", [
+ "$parse", "$window", function($parse, $window) {
+ return {
+ restrict: "A",
+ link: function($scope, element, attrs) {
+ var handler;
+ handler = function($event) {
+ var callbackFn;
+ callbackFn = $parse(attrs.macWindowResize);
+ $scope.$apply(function() {
+ return callbackFn($scope, {
+ $event: $event
+ });
+ });
+ return true;
+ };
+ angular.element($window).bind("resize", handler);
+ return $scope.$on("destroy", function() {
+ return angular.element($window).unbind("resize", handler);
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name mac-focus-on-event
+
+@description
+Scroll window to the element and focus on the element
+
+@param {String} mac-focus-on-event Event to focus on element
+@param {Boolean} mac-focus-on-event-scroll Scroll to element location or not
+ */
+angular.module("Mac").directive("macFocusOnEvent", [
+ "$timeout", function($timeout) {
+ return function(scope, element, attributes) {
+ return scope.$on(attributes.macFocusOnEvent, function() {
+ return $timeout(function() {
+ var x, y;
+ element.focus();
+ if (attributes.macFocusOnEventScroll) {
+ x = window.scrollX;
+ y = window.scrollY;
+ return window.scrollTo(x, y);
+ }
+ }, 0, false);
+ });
+ };
+ }
+]);
+
+angular.module("Mac").factory("keys", function() {
+ return {
+ CANCEL: 3,
+ HELP: 6,
+ BACKSPACE: 8,
+ TAB: 9,
+ CLEAR: 12,
+ ENTER: 13,
+ RETURN: 13,
+ SHIFT: 16,
+ CONTROL: 17,
+ ALT: 18,
+ PAUSE: 19,
+ CAPS_LOCK: 20,
+ ESCAPE: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ PRINT_SCREEN: 44,
+ INSERT: 45,
+ DELETE: 46,
+ ZERO: 48,
+ ONE: 49,
+ TWO: 50,
+ THREE: 51,
+ FOUR: 52,
+ FIVE: 53,
+ SIX: 54,
+ SEVEN: 55,
+ EIGHT: 56,
+ NINE: 57,
+ SEMICOLON: 59,
+ EQUALS: 61,
+ COMMAND: 91,
+ A: 65,
+ B: 66,
+ C: 67,
+ D: 68,
+ E: 69,
+ F: 70,
+ G: 71,
+ H: 72,
+ I: 73,
+ J: 74,
+ K: 75,
+ L: 76,
+ M: 77,
+ N: 78,
+ O: 79,
+ P: 80,
+ Q: 81,
+ R: 82,
+ S: 83,
+ T: 84,
+ U: 85,
+ V: 86,
+ W: 87,
+ X: 88,
+ Y: 89,
+ Z: 90,
+ CONTEXT_MENU: 93,
+ NUMPAD0: 96,
+ NUMPAD1: 97,
+ NUMPAD2: 98,
+ NUMPAD3: 99,
+ NUMPAD4: 100,
+ NUMPAD5: 101,
+ NUMPAD6: 102,
+ NUMPAD7: 103,
+ NUMPAD8: 104,
+ NUMPAD9: 105,
+ MULTIPLY: 106,
+ ADD: 107,
+ SEPARATOR: 108,
+ SUBTRACT: 109,
+ DECIMAL: 110,
+ DIVIDE: 111,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123,
+ F13: 124,
+ F14: 125,
+ F15: 126,
+ F16: 127,
+ F17: 128,
+ F18: 129,
+ F19: 130,
+ F20: 131,
+ F21: 132,
+ F22: 133,
+ F23: 134,
+ F24: 135,
+ NUM_LOCK: 144,
+ SCROLL_LOCK: 145,
+ COMMA: 188,
+ PERIOD: 190,
+ SLASH: 191,
+ BACK_QUOTE: 192,
+ OPEN_BRACKET: 219,
+ BACK_SLASH: 220,
+ CLOSE_BRACKET: 221,
+ QUOTE: 222,
+ META: 224
+ };
+});
+
+
+/*
+@chalk overview
+@name Menu
+
+@description
+A directive for creating a menu with multiple items
+
+Menu allows for custom html templating for each item.
+
+Since macMenu is using ngRepeat, some ngRepeat properties along with `item` are exposed on the local scope of each template instance, including:
+
+| Variable | Type | Details |
+|-----------|---------|-----------------------------------------------------------------------------|
+| `$index` | Number | iterator offset of the repeated element (0..length-1) |
+| `$first` | Boolean | true if the repeated element is first in the iterator. |
+| `$middle` | Boolean | true if the repeated element is between the first and last in the iterator. |
+| `$last` | Boolean | true if the repeated element is last in the iterator. |
+| `$even` | Boolean | true if the iterator position `$index` is even (otherwise false). |
+| `$odd` | Boolean | true if the iterator position `$index` is odd (otherwise false). |
+| `item` | Object | item object |
+
+To use custom templating
+```
+<mac-menu>
+ <span> {{item.label}} </span>
+</mac-menu>
+```
+
+Template default to `{{item.label}}` if not defined
+
+@param {Expression} mac-menu-items List of items to display in the menu
+ Each item should have a `label` key as display text
+@param {Function} mac-menu-select Callback on select
+- `index` - {Integer} Item index
+@param {Object} mac-menu-style Styles apply to the menu
+@param {Expression} mac-menu-index Index of selected item
+ */
+angular.module("Mac").directive("macMenu", [
+ function() {
+ return {
+ restrict: "EA",
+ replace: true,
+ template: "<div ng-style=\"style\" class=\"mac-menu\"> <ul> <li class=\"mac-menu-item\" ng-class=\"{'active': $index == index}\" ng-click=\"selectItem($index)\" ng-mouseenter=\"setIndex($index)\" ng-repeat=\"item in items\" mac-menu-transclude=\"mac-menu-transclude\"> </li> </ul></div>",
+ transclude: true,
+ controller: angular.noop,
+ scope: {
+ items: "=macMenuItems",
+ style: "=macMenuStyle",
+ select: "&macMenuSelect",
+ pIndex: "=macMenuIndex"
+ },
+ link: function($scope, element, attrs, ctrls) {
+ $scope.selectItem = function(index) {
+ return $scope.select({
+ index: index
+ });
+ };
+ $scope.setIndex = function(index) {
+ $scope.index = index;
+ if (attrs.macMenuIndex != null) {
+ return $scope.pIndex = parseInt(index);
+ }
+ };
+ if (attrs.macMenuIndex != null) {
+ $scope.$watch("pIndex", function(value) {
+ return $scope.index = parseInt(value);
+ });
+ }
+ return $scope.$watch("items.length", function(value) {
+ if (!!value) {
+ return attrs.$addClass("visible");
+ } else {
+ return attrs.$removeClass("visible");
+ }
+ });
+ }
+ };
+ }
+]).directive("macMenuTransclude", [
+ "$compile", function($compile) {
+ return {
+ link: function($scope, element, attrs, ctrls, transclude) {
+ return transclude($scope, function(clone) {
+ element.empty();
+ if (clone.length === 0) {
+ clone = $compile("<span>{{item.label}}</span>")($scope);
+ }
+ return element.append(clone);
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name mac-modal (element)
+@description
+Element directive to define the modal dialog. Modal content is transcluded into a
+modal template
+
+@param {Boolean} mac-modal-keyboard Allow closing modal with keyboard (default false)
+@param {Boolean} mac-modal-overlay-close Allow closing modal when clicking on overlay (default false)
+@param {Boolean} mac-modal-resize Allow modal to resize on window resize event (default true)
+@param {Integer} mac-modal-topOffset Top offset when the modal is larger than window height (default 20)
+@param {Expr} mac-modal-open Callback when the modal is opened
+@param {Expr} mac-modal-before-show Callback before showing the modal
+@param {Expr} mac-modal-after-show Callback when modal is visible with CSS transitions completed
+@param {Expr} mac-modal-before-hide Callback before hiding the modal
+@param {Expr} mac-modal-after-hide Callback when modal is hidden from the user with CSS transitions completed
+@param {Boolean} mac-modal-position Calculate size and position with JS (default true)
+ */
+angular.module("Mac").directive("macModal", [
+ "$parse", "modal", "util", function($parse, modal, util) {
+ return {
+ restrict: "E",
+ template: modal.modalTemplate,
+ replace: true,
+ transclude: true,
+ link: function($scope, element, attrs, controller, transclude) {
+ var callback, key, opts, regId, registerModal, _i, _len, _ref;
+ transclude($scope, function(clone) {
+ return angular.element(element[0].getElementsByClassName("mac-modal-content-wrapper")).replaceWith(clone);
+ });
+ opts = util.extendAttributes("macModal", modal.defaults, attrs);
+ regId = null;
+ if (opts.overlayClose) {
+ element.on("click", function($event) {
+ if (angular.element($event.target).hasClass("mac-modal-overlay")) {
+ return $scope.$apply(function() {
+ return modal.hide();
+ });
+ }
+ });
+ }
+ _ref = ["beforeShow", "afterShow", "beforeHide", "afterHide", "open"];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ callback = _ref[_i];
+ key = "macModal" + (util.capitalize(callback));
+ opts[callback] = $parse(attrs[key]) || angular.noop;
+ }
+ registerModal = function(id) {
+ if ((id != null) && id) {
+ regId = id;
+ return modal.register(id, element, opts);
+ }
+ };
+ if (attrs.id) {
+ registerModal(attrs.id);
+ } else {
+ attrs.$observe("macModal", function(id) {
+ return registerModal(id);
+ });
+ }
+ return $scope.$on("$destroy", function() {
+ if (regId) {
+ return modal.unregister(regId);
+ }
+ });
+ }
+ };
+ }
+]).directive("macModal", [
+ "$parse", "modal", function($parse, modal) {
+ return {
+ restrict: "A",
+ link: function($scope, element, attrs) {
+ if (!attrs.macModal) {
+ return;
+ }
+ element.bind("click", function() {
+ return $scope.$apply(function() {
+ var data;
+ data = $parse(attrs.macModalData)($scope) || {};
+ return modal.show(attrs.macModal, {
+ data: data,
+ scope: $scope
+ });
+ });
+ });
+ }
+ };
+ }
+]).directive("macModalClose", [
+ "modal", function(modal) {
+ return {
+ restrict: "A",
+ link: function($scope, element, attrs) {
+ return element.bind("click", function() {
+ return $scope.$apply(function() {
+ return modal.hide();
+ });
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Placeholder
+
+@description
+Dynamically fill out the placeholder text of input
+
+@param {String} mac-placeholder Variable that contains the placeholder text
+ */
+angular.module("Mac").directive("macPlaceholder", function() {
+ return {
+ restrict: "A",
+ link: function($scope, element, attrs) {
+ return $scope.$watch(attrs.macPlaceholder, function(value) {
+ return attrs.$set("placeholder", value);
+ });
+ }
+ };
+});
+
+
+/*
+@chalk
+@name mac-popover (attribute)
+@description
+Mac popover trigger directive. Without using mac-popover-child-popover, the last
+popover will be closed automatically
+
+@param {String} mac-popover ID of the popover to show
+@param {Boolean} mac-popover-fixed Determine if the popover is fixed
+@param {Boolean} mac-popover-child-popover If the popover is child of another popover (default false)
+@param {Integer} mac-popover-offset-x Extra x offset (default 0)
+@param {Integer} mac-popover-offset-y Extra y offset (default 0)
+@param {String} mac-popover-trigger Trigger option, click | hover | focus (default click)
+- click: Popover only opens when user click on trigger
+- hover: Popover shows when user hover on trigger
+- focus: Popover shows when focus on input element
+@param {String} mac-popover-exclude CSV of popover id that can't be shown at the same time
+ */
+var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+angular.module("Mac").directive("macPopover", [
+ "$timeout", "popover", "util", function($timeout, popover, util) {
+ return {
+ restrict: "A",
+ link: function(scope, element, attrs) {
+ var clearDelays, closeDelayId, delayId, exclude, excludeList, hide, options, show;
+ options = util.extendAttributes("macPopover", popover.defaults, attrs);
+ exclude = attrs.macPopoverExclude || "";
+ excludeList = exclude ? exclude.split(",") : [];
+ delayId = null;
+ closeDelayId = null;
+ clearDelays = function() {
+ if (delayId != null) {
+ $timeout.cancel(delayId);
+ }
+ if (closeDelayId != null) {
+ return $timeout.cancel(closeDelayId);
+ }
+ };
+ show = function(id, delay) {
+ if (delay == null) {
+ delay = 0;
+ }
+ clearDelays();
+ delayId = $timeout(function() {
+ var last, _ref;
+ last = popover.last();
+ if ((last != null) && (!excludeList.length || (_ref = last.id, __indexOf.call(excludeList, _ref) >= 0) || last.id === id)) {
+ popover.hide();
+ if (element[0] === last.element[0]) {
+ return true;
+ }
+ }
+ options.scope = scope;
+ return popover.show(id, element, options);
+ }, delay);
+ return true;
+ };
+ hide = function(element, delay) {
+ if (delay == null) {
+ delay = 0;
+ }
+ clearDelays();
+ return closeDelayId = $timeout(function() {
+ return popover.hide(element);
+ }, delay);
+ };
+ return attrs.$observe("macPopover", function(id) {
+ var hideEvent, showEvent;
+ if (!id) {
+ return;
+ }
+ if (options.trigger === "click") {
+ return element.bind("click", function() {
+ return show(id, 0);
+ });
+ } else {
+ showEvent = options.trigger === "focus" ? "focusin" : "mouseenter";
+ hideEvent = options.trigger === "focus" ? "focusout" : "mouseleave";
+ element.bind(showEvent, function() {
+ return show(id, 400);
+ });
+ return element.bind(hideEvent, function() {
+ return hide(element, 500);
+ });
+ }
+ });
+ }
+ };
+ }
+]).directive("macPopover", [
+ "popover", "util", function(popover, util) {
+ return {
+ restrict: "E",
+ compile: function(element, attrs) {
+ var opts;
+ if (!attrs.id) {
+ throw Error("macPopover: Missing id");
+ }
+ opts = util.extendAttributes("macPopover", popover.popoverDefaults, attrs);
+ angular.extend(opts, {
+ template: element.html()
+ });
+ return function($scope, element, attrs) {
+ return attrs.$observe("id", function(value) {
+ popover.register(value, opts);
+ return element.replaceWith(document.createComment("macPopover: " + attrs.id));
+ });
+ };
+ }
+ };
+ }
+]).directive("macPopoverFillContent", [
+ "$compile", function($compile) {
+ return {
+ restrict: "A",
+ link: function($scope, element, attrs) {
+ element.html($scope.macPopoverTemplate);
+ return $compile(element.contents())($scope);
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name mac-scroll-spy
+
+@description
+Element to spy scroll event on
+
+@param {Integer} mac-scroll-spy-offset Top offset when calculating scroll position
+ */
+angular.module("Mac").directive("macScrollSpy", [
+ "$window", "scrollSpy", "scrollSpyDefaults", "util", function($window, scrollSpy, defaults, util) {
+ return {
+ link: function($scope, element, attrs) {
+ var options, spyElement;
+ options = util.extendAttributes("macScrollSpy", defaults, attrs);
+ spyElement = element[0].tagName === "BODY" ? angular.element($window) : element;
+ return spyElement.bind("scroll", function($event) {
+ var anchors, i, maxScroll, scrollHeight, scrollTop, _i, _ref;
+ scrollTop = spyElement.scrollTop() + options.offset;
+ scrollHeight = this.scrollHeight || element[0].scrollHeight;
+ maxScroll = scrollHeight - spyElement.height();
+ if (!scrollSpy.registered.length) {
+ return true;
+ }
+ if (scrollTop >= maxScroll) {
+ return scrollSpy.setActive(scrollSpy.last());
+ }
+ for (i = _i = 0, _ref = scrollSpy.registered.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
+ anchors = scrollSpy.registered;
+ if (scrollSpy.active.id !== anchors[i].id && scrollTop >= anchors[i].top && (!anchors[i + 1] || scrollTop <= anchors[i + 1].top)) {
+ $scope.$apply(function() {
+ return scrollSpy.setActive(anchors[i]);
+ });
+ return true;
+ }
+ }
+ });
+ }
+ };
+ }
+]).directive("macScrollSpyAnchor", [
+ "scrollSpy", function(scrollSpy) {
+ return {
+ link: function($scope, element, attrs) {
+ var id, observeKey, registered, registering;
+ id = attrs.id || attrs.macScrollSpyAnchor;
+ registered = false;
+ if (!id) {
+ throw new Error("Missing scroll spy anchor id");
+ }
+ registering = function() {
+ scrollSpy.register(id, element);
+ if (!registered) {
+ $scope.$on("$destroy", function() {
+ return scrollSpy.unregister(id);
+ });
+ }
+ return registered = true;
+ };
+ $scope.$on("refresh-scroll-spy", registering);
+ if (/{{(.*)}}/.test(id)) {
+ observeKey = attrs.id ? "id" : "macScrollSpyAnchor";
+ return attrs.$observe(observeKey, function(value) {
+ if ((value != null) && value) {
+ id = value;
+ return registering();
+ }
+ });
+ } else {
+ return registering();
+ }
+ }
+ };
+ }
+]).directive("macScrollSpyTarget", [
+ "scrollSpy", function(scrollSpy) {
+ return {
+ link: function($scope, element, attrs) {
+ var highlightClass, register, registered, target;
+ target = attrs.macScrollSpyTarget;
+ highlightClass = attrs.macScrollSpyTargetClass || "active";
+ registered = false;
+ if (!target) {
+ throw new Error("Missing scroll spy target name");
+ }
+ register = function(id) {
+ var callback;
+ if (!id) {
+ return;
+ }
+ callback = function(active) {
+ var action;
+ action = id === active.id ? "addClass" : "removeClass";
+ return element[action](highlightClass);
+ };
+ if (scrollSpy.active != null) {
+ callback(scrollSpy.active);
+ }
+ if (!registered) {
+ scrollSpy.addListener(callback);
+ return $scope.$on("$destroy", function() {
+ return scrollSpy.removeListener(callback);
+ });
+ }
+ };
+ if (/{{(.*)}}/.test(target)) {
+ return attrs.$observe("macScrollSpyTarget", function(value) {
+ return register(value);
+ });
+ } else {
+ return register(target);
+ }
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Spinner
+
+@description
+A directive for generating spinner
+
+@param {Integer} mac-spinner-size The size of the spinner (default 16)
+@param {Integer} mac-spinner-z-index The z-index (default inherit)
+@param {String} mac-spinner-color Color of all the bars (default #2f3035)
+ */
+angular.module("Mac").directive("macSpinner", [
+ "util", function(util) {
+ return {
+ restrict: "E",
+ replace: true,
+ template: "<div class=\"mac-spinner\"></div>",
+ compile: function(element, attrs) {
+ var animateCss, bar, bars, degree, delay, i, prefixes, styl, transformCss, updateBars, vendor, _i;
+ prefixes = ["webkit", "Moz", "ms", "O"];
+ bars = [];
+ vendor = function(el, name) {
+ var prefix, _i, _len;
+ name = util.capitalize(name);
+ for (_i = 0, _len = prefixes.length; _i < _len; _i++) {
+ prefix = prefixes[_i];
+ if (el.style[prefix + name] != null) {
+ return prefix + name;
+ }
+ }
+ return name;
+ };
+ updateBars = function(propertyName, value) {
+ var bar, property, propertyValue, _i, _len, _results;
+ if (angular.isObject(propertyName)) {
+ for (property in propertyName) {
+ propertyValue = propertyName[property];
+ updateBars(property, propertyValue);
+ }
+ return;
+ }
+ _results = [];
+ for (_i = 0, _len = bars.length; _i < _len; _i++) {
+ bar = bars[_i];
+ _results.push(bar.style[propertyName] = value);
+ }
+ return _results;
+ };
+ animateCss = vendor(element[0], "animation");
+ transformCss = vendor(element[0], "transform");
+ for (i = _i = 0; _i <= 9; i = ++_i) {
+ delay = i * 0.1 - 1 + (!i);
+ degree = i * 36;
+ styl = {};
+ bar = angular.element("<div class=\"bar\"></div>");
+ bars.push(bar[0]);
+ styl[animateCss] = "fade 1s linear infinite " + delay + "s";
+ styl[transformCss] = "rotate(" + degree + "deg) translate(0, 130%)";
+ bar.css(styl);
+ element.append(bar);
+ }
+ return function($scope, element, attrs) {
+ var defaults, setSpinnerSize;
+ defaults = {
+ size: 16,
+ zIndex: "inherit",
+ color: "#2f3035"
+ };
+ setSpinnerSize = function(size) {
+ updateBars({
+ height: size * 0.32 + "px",
+ left: size * 0.445 + "px",
+ top: size * 0.37 + "px",
+ width: size * 0.13 + "px",
+ borderRadius: size * 0.32 * 2 + "px",
+ position: "absolute"
+ });
+ if (!isNaN(+size) && angular.isNumber(+size)) {
+ size = "" + size + "px";
+ }
+ return element.css({
+ height: size,
+ width: size
+ });
+ };
+ if (attrs.macSpinnerSize != null) {
+ attrs.$observe("macSpinnerSize", function(value) {
+ if ((value != null) && value) {
+ return setSpinnerSize(value);
+ }
+ });
+ } else {
+ setSpinnerSize(defaults.size);
+ }
+ attrs.$observe("macSpinnerZIndex", function(value) {
+ if ((value != null) && value) {
+ return element.css("z-index", value);
+ }
+ });
+ if (attrs.macSpinnerColor != null) {
+ return attrs.$observe("macSpinnerColor", function(value) {
+ if ((value != null) && value) {
+ return updateBars("background", value);
+ }
+ });
+ } else {
+ return updateBars("background", defaults.color);
+ }
+ };
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Tag Autocomplete
+
+@description
+A directive for generating tag input with autocomplete support on text input.
+Tag autocomplete has priority 800
+
+@dependencies
+- mac-autocomplete
+- mac-menu
+
+@param {String} mac-tag-autocomplete-url Url to fetch autocomplete dropdown list data.
+mac-tag-autocomplete-url and mac-tag-autocomplete-source cannot be used together. Url
+will always take priority over mac-tag-autocomplete-source.
+@param {String} mac-tag-autocomplete-source Data to use.
+Source support multiple types:
+- Array: An array can be used for local data and there are two supported formats:
+ - An array of strings: ["Item1", "Item2"]
+ - An array of objects with mac-autocomplete-label key: [{name:"Item1"}, {name:"Item2"}]
+- String: Using a string as the source is the same as passing the variable into mac-autocomplete-url
+- Function: A callback when querying for data. The callback receive two arguments:
+ - {String} Value currently in the text input
+ - {Function} A response callback which expects a single argument, data to user. The data will be
+ populated on the menu and the menu will adjust accordingly
+@param {String} mac-tag-autocomplete-value The value to be sent back upon selection (default "id")
+@param {String} mac-tag-autocomplete-label The label to display to the users (default "name")
+@param {Expr} mac-tag-autocomplete-model Model for autocomplete
+@param {Array} mac-tag-autocomplete-selected The list of elements selected by the user (required)
+@param {String} mac-tag-autocomplete-query The query parameter on GET command (defualt "q")
+@param {Integer} mac-tag-autocomplete-delay Time delayed on fetching autocomplete data after keyup (default 800)
+@param {String} mac-tag-autocomplete-placeholder Placeholder text of the text input (default "")
+@param {Boolean} mac-tag-autocomplete-disabled If autocomplete is enabled or disabled (default false)
+@param {Expr} mac-tag-autocomplete-on-enter When autocomplete is disabled, this function is called on enter, Should return either string, object or boolean. If false, item is not added
+- `item` - {String} User input
+@param {String} mac-tag-autocomplete-events A CSV list of events to attach functions to
+@param {Expr} mac-tag-autocomplete-on- Function to be called when specified event is fired
+- `event` - {Object} jQuery event
+- `value` - {String} Value in the input text
+
+@param {Event} mac-tag-autocomplete-clear-input $broadcast message; clears text input when received
+ */
+var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+angular.module("Mac").directive("macTagAutocomplete", [
+ "$parse", "$timeout", "keys", "util", function($parse, $timeout, keys, util) {
+ return {
+ restrict: "E",
+ template: "<div class=\"mac-tag-autocomplete\"> <ul class=\"mac-tag-list\"> <li ng-repeat=\"tag in selected\" class=\"mac-tag mac-label\"> <div ng-click=\"selected.splice($index, 1)\" class=\"mac-tag-close\">&times;</div> <span class=\"tag-label\">{{getTagLabel(tag)}}</span> </li> <li ng-class=\"{'fullwidth': !selected.length}\" class=\"mac-tag mac-input-tag\"> <mac-autocomplete class=\"text-input mac-autocomplete\" ng-keydown=\"onKeyDown($event)\" ng-model=\"textInput\" mac-autocomplete-disabled=\"disabled\" mac-autocomplete-on-select=\"onSelect(selected)\" mac-autocomplete-on-success=\"onSuccess(data)\" mac-placeholder=\"autocompletePlaceholder\"></mac-autocomplete> </li> </ul></div>",
+ replace: true,
+ priority: 800,
+ scope: {
+ url: "=macTagAutocompleteUrl",
+ placeholder: "=macTagAutocompletePlaceholder",
+ selected: "=macTagAutocompleteSelected",
+ source: "=macTagAutocompleteSource",
+ disabled: "=macTagAutocompleteDisabled",
+ model: "=macTagAutocompleteModel",
+ onEnter: "&macTagAutocompleteOnEnter",
+ onKeydown: "&macTagAutocompleteOnKeydown"
+ },
+ compile: function(element, attrs) {
+ var attrsObject, delay, labelGetter, labelKey, queryKey, textInput, useSource, valueGetter, valueKey;
+ valueKey = attrs.macTagAutocompleteValue;
+ if (valueKey == null) {
+ valueKey = "id";
+ }
+ valueGetter = $parse(valueKey);
+ labelKey = attrs.macTagAutocompleteLabel;
+ if (labelKey == null) {
+ labelKey = "name";
+ }
+ labelGetter = $parse(labelKey);
+ queryKey = attrs.macTagAutocompleteQuery || "q";
+ delay = +attrs.macTagAutocompleteDelay || 800;
+ useSource = false;
+ textInput = angular.element(element[0].getElementsByClassName("mac-autocomplete"));
+ attrsObject = {
+ "mac-autocomplete-label": labelKey,
+ "mac-autocomplete-query": queryKey,
+ "mac-autocomplete-delay": delay
+ };
+ if (attrs.macTagAutocompleteUrl != null) {
+ attrsObject["mac-autocomplete-url"] = "url";
+ } else if (useSource = attrs.macTagAutocompleteSource != null) {
+ attrsObject["mac-autocomplete-source"] = "autocompleteSource";
+ }
+ textInput.attr(attrsObject);
+ return function($scope, element, attrs) {
+ var updateAutocompleteSource, watchFn;
+ $scope.textInput = "";
+ $scope.autocompleteSource = angular.isArray($scope.source) ? [] : $scope.source;
+ if (attrs.macTagAutocompleteModel != null) {
+ $scope.$watch("textInput", function(value) {
+ return $scope.model = value;
+ });
+ $scope.$watch("model", function(value) {
+ return $scope.textInput = value;
+ });
+ }
+ element.bind("click", function() {
+ var textInputDOM;
+ textInputDOM = element[0].getElementsByClassName("mac-autocomplete");
+ return textInputDOM[0].focus();
+ });
+ $scope.getTagLabel = function(tag) {
+ if (labelKey) {
+ return labelGetter(tag);
+ } else {
+ return tag;
+ }
+ };
+ $timeout(function() {
+ var capitalized, eventFn, events, name, _i, _len, _ref, _results;
+ if ((events = attrs.macTagAutocompleteEvents)) {
+ textInput = angular.element(element[0].getElementsByClassName("text-input"));
+ _ref = events.split(",");
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ name = _ref[_i];
+ name = util.trim(name);
+ capitalized = util.capitalize(name);
+ eventFn = attrs["macTagAutocompleteOn" + capitalized];
+ if (!(eventFn && name !== "keydown")) {
+ continue;
+ }
+ _results.push((function(name, eventFn) {
+ return textInput.bind(name, function($event) {
+ var expression;
+ expression = $parse(eventFn);
+ return $scope.$apply(function() {
+ return expression($scope.$parent, {
+ $event: $event,
+ item: $scope.textInput
+ });
+ });
+ });
+ })(name, eventFn));
+ }
+ return _results;
+ }
+ }, 0, false);
+ updateAutocompleteSource = function() {
+ var difference, item, selectedValues, sourceValues, _ref;
+ $scope.autocompletePlaceholder = ((_ref = $scope.selected) != null ? _ref.length : void 0) ? "" : $scope.placeholder;
+ if (!(useSource && angular.isArray($scope.source))) {
+ $scope.autocompleteSource = $scope.source;
+ return;
+ }
+ sourceValues = (function() {
+ var _i, _len, _ref1, _results;
+ _ref1 = $scope.source || [];
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ item = _ref1[_i];
+ _results.push(valueGetter(item));
+ }
+ return _results;
+ })();
+ selectedValues = (function() {
+ var _i, _len, _ref1, _results;
+ _ref1 = $scope.selected || [];
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ item = _ref1[_i];
+ _results.push(valueGetter(item));
+ }
+ return _results;
+ })();
+ difference = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = sourceValues.length; _i < _len; _i++) {
+ item = sourceValues[_i];
+ if (__indexOf.call(selectedValues, item) < 0) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return $scope.autocompleteSource = (function() {
+ var _i, _len, _ref1, _ref2, _results;
+ _ref1 = $scope.source || [];
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ item = _ref1[_i];
+ if (_ref2 = valueGetter(item), __indexOf.call(difference, _ref2) >= 0) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ };
+ if (useSource) {
+ watchFn = angular.isArray($scope.source) ? "$watchCollection" : "$watch";
+ $scope[watchFn]("source", updateAutocompleteSource);
+ }
+ $scope.$watchCollection("selected", updateAutocompleteSource);
+ $scope.onKeyDown = function($event) {
+ var stroke, _base;
+ stroke = $event.which || $event.keyCode;
+ switch (stroke) {
+ case keys.BACKSPACE:
+ if (!$scope.textInput) {
+ if (typeof (_base = $scope.selected).pop === "function") {
+ _base.pop();
+ }
+ }
+ break;
+ case keys.ENTER:
+ if ($scope.textInput.length > 0 && $scope.disabled) {
+ $scope.onSelect($scope.textInput);
+ }
+ }
+ if (attrs.macTagAutocompleteOnKeydown != null) {
+ if (typeof $scope.onKeydown === "function") {
+ $scope.onKeydown({
+ $event: $event,
+ value: $scope.textInput
+ });
+ }
+ }
+ return true;
+ };
+ $scope.onSuccess = function(data) {
+ var existingValues, item;
+ existingValues = (function() {
+ var _i, _len, _ref, _results;
+ _ref = $scope.selected || [];
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ _results.push(valueGetter(item));
+ }
+ return _results;
+ })();
+ return (function() {
+ var _i, _len, _ref, _ref1, _results;
+ _ref = data.data;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (_ref1 = valueGetter(item) || item, __indexOf.call(existingValues, _ref1) < 0) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ };
+ $scope.onSelect = function(item) {
+ if (attrs.macTagAutocompleteOnEnter != null) {
+ item = $scope.onEnter({
+ item: item
+ });
+ }
+ if (item) {
+ $scope.selected.push(item);
+ }
+ return $timeout(function() {
+ return $scope.textInput = "";
+ }, 0);
+ };
+ return $scope.$on("mac-tag-autocomplete-clear-input", function() {
+ return $scope.textInput = "";
+ });
+ };
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Time
+@description
+A directive for creating a time input field. Time input can use any `ng-` attributes support by text input type.
+
+@param {String} ng-model Assignable angular expression to data-bind to
+Clearing model by setting it to null or '' will set model back to default value
+@param {String} name Property name of the form under which the control is published
+@param {String} required Adds `required` validation error key if the value is not entered.
+@param {String} ng-required Adds `required` attribute and `required` validation constraint to
+ the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ `required` when you want to data-bind to the `required` attribute.
+@param {String} ng-pattern Sets `pattern` validation error key if the value does not match the
+ RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ patterns defined as scope expressions.
+@param {String} ng-change Angular expression to be executed when input changes due to user interaction with the input element.
+@param {String} ng-disabled Enable or disable time input
+
+@param {String} mac-time-default If model is undefined, use this as the starting value (default 12:00 PM)
+ */
+angular.module("Mac").directive("macTime", [
+ "$filter", "$timeout", "keys", "util", function($filter, $timeout, keys, util) {
+ var defaults;
+ defaults = {
+ "default": "12:00 AM"
+ };
+ return {
+ restrict: "E",
+ require: "ngModel",
+ replace: true,
+ template: "<input class=\"mac-date-time\" type=\"text\" maxlength=\"8\">",
+ link: function($scope, element, attrs, ngModelCtrl) {
+ var getSelection, incrementHour, incrementMinute, initializeTime, opts, selectHours, selectMeridian, selectMinutes, selectNextSection, selectPreviousSection, selectRange, setMeridian, time, timeValidator, toggleMeridian, updateInput, updateTime;
+ opts = util.extendAttributes("macTime", defaults, attrs);
+ time = null;
+ if (!attrs.placeholder) {
+ attrs.$set("placeholder", "--:--");
+ }
+ timeValidator = function(value) {
+ if (!value || util.timeRegex.exec(value)) {
+ ngModelCtrl.$setValidity("time", true);
+ return value;
+ } else {
+ ngModelCtrl.$setValidity("time", false);
+ return void 0;
+ }
+ };
+ ngModelCtrl.$formatters.push(timeValidator);
+ ngModelCtrl.$parsers.push(timeValidator);
+ (initializeTime = function() {
+ var currentDate;
+ currentDate = new Date().toDateString();
+ time = new Date(currentDate + " " + opts["default"]);
+ if (isNaN(time.getTime())) {
+ return time = new Date(currentDate + " " + defaults["default"]);
+ }
+ })();
+ getSelection = function() {
+ var start;
+ start = element[0].selectionStart;
+ switch (false) {
+ case !((0 <= start && start < 3)):
+ return "hour";
+ case !((3 <= start && start < 6)):
+ return "minute";
+ case !((6 <= start && start < 9)):
+ return "meridian";
+ }
+ };
+ selectRange = function(start, end) {
+ return $timeout(function() {
+ return element[0].setSelectionRange(start, end);
+ }, 0, false);
+ };
+ selectHours = function() {
+ return selectRange(0, 2);
+ };
+ selectMinutes = function() {
+ return selectRange(3, 5);
+ };
+ selectMeridian = function() {
+ return selectRange(6, 8);
+ };
+ selectNextSection = function() {
+ switch (getSelection()) {
+ case "hour":
+ return selectMinutes();
+ case "minute":
+ case "meridian":
+ return selectMeridian();
+ }
+ };
+ selectPreviousSection = function() {
+ switch (getSelection()) {
+ case "hour":
+ case "minute":
+ return selectHours();
+ case "meridian":
+ return selectMinutes();
+ }
+ };
+ setMeridian = function(meridian) {
+ var hours;
+ hours = time.getHours();
+ if (hours >= 12 && meridian === "AM") {
+ hours -= 12;
+ }
+ if (hours < 12 && meridian === "PM") {
+ hours += 12;
+ }
+ return time.setHours(hours);
+ };
+ toggleMeridian = function() {
+ var hours;
+ hours = time.getHours();
+ return time.setHours((hours + 12) % 24);
+ };
+ incrementHour = function(change) {
+ return time.setHours(time.getHours() + change);
+ };
+ incrementMinute = function(change) {
+ return time.setMinutes(time.getMinutes() + change);
+ };
+ updateInput = function() {
+ var displayTime;
+ displayTime = $filter("date")(time.getTime(), "hh:mm a");
+ if (displayTime !== ngModelCtrl.$viewValue) {
+ ngModelCtrl.$setViewValue(displayTime);
+ return ngModelCtrl.$render();
+ }
+ };
+ updateTime = function() {
+ var hours, meridian, minutes, timeMatch;
+ if (timeMatch = util.timeRegex.exec(ngModelCtrl.$modelValue)) {
+ hours = +timeMatch[1];
+ minutes = +timeMatch[2];
+ meridian = timeMatch[3];
+ if (meridian === "PM" && hours !== 12) {
+ hours += 12;
+ }
+ if (meridian === "AM" && hours === 12) {
+ hours = 0;
+ }
+ return time.setHours(hours, minutes);
+ }
+ };
+ element.on('blur', function(event) {
+ return $scope.$apply(function() {
+ return updateInput();
+ });
+ });
+ element.on('click', function(event) {
+ return $scope.$apply(function() {
+ updateTime();
+ updateInput();
+ switch (getSelection()) {
+ case "hour":
+ return selectHours();
+ case "minute":
+ return selectMinutes();
+ case "meridian":
+ return selectMeridian();
+ }
+ });
+ });
+ element.on('keydown', function(event) {
+ var key;
+ key = event.which;
+ if (key !== keys.UP && key !== keys.DOWN && key !== keys.LEFT && key !== keys.RIGHT && key !== keys.A && key !== keys.P) {
+ return true;
+ }
+ event.preventDefault();
+ return $scope.$apply(function() {
+ var change, meridianSelected;
+ switch (key) {
+ case keys.UP:
+ case keys.DOWN:
+ change = key === keys.UP ? 1 : -1;
+ switch (getSelection()) {
+ case "hour":
+ incrementHour(change);
+ selectHours();
+ break;
+ case "minute":
+ incrementMinute(change);
+ selectMinutes();
+ break;
+ case "meridian":
+ toggleMeridian();
+ selectMeridian();
+ }
+ return updateInput();
+ case keys.LEFT:
+ case keys.RIGHT:
+ switch (key) {
+ case keys.LEFT:
+ selectPreviousSection();
+ break;
+ case keys.RIGHT:
+ selectNextSection();
+ }
+ return updateInput();
+ case keys.A:
+ case keys.P:
+ meridianSelected = getSelection() === "meridian";
+ switch (false) {
+ case !(meridianSelected && key === keys.A):
+ setMeridian("AM");
+ break;
+ case !(meridianSelected && key === keys.P):
+ setMeridian("PM");
+ }
+ updateInput();
+ return selectMeridian();
+ }
+ });
+ });
+ return element.on('keyup', function(event) {
+ var key;
+ key = event.which;
+ if (!((keys.NUMPAD0 <= key && key <= keys.NUMPAD9) || (keys.ZERO <= key && key <= keys.NINE))) {
+ event.preventDefault();
+ }
+ return $scope.$apply(function() {
+ return updateTime();
+ });
+ });
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Tooltip
+
+@description
+Tooltip directive
+
+@param {String} mac-tooltip Text to show in tooltip
+@param {String} mac-tooltip-direction Direction of tooltip (default 'top')
+@param {String} mac-tooltip-trigger How tooltip is triggered (default 'hover')
+@param {Boolean} mac-tooltip-inside Should the tooltip be appended inside element (default false)
+@param {Expr} mac-tooltip-disabled Disable and enable tooltip
+ */
+
+/*
+NOTE: This directive does not use $animate to append and remove DOM element or
+ add and remove classes in order to optimize showing tooltips by eliminating
+ the need for firing a $digest cycle.
+ */
+angular.module("Mac").directive("macTooltip", [
+ "$timeout", "util", function($timeout, util) {
+ return {
+ restrict: "A",
+ link: function(scope, element, attrs) {
+ var closeDelay, defaults, disabled, enabled, opts, removeTip, showTip, text, toggle, tooltip;
+ tooltip = null;
+ text = "";
+ enabled = false;
+ disabled = false;
+ closeDelay = null;
+ defaults = {
+ direction: "top",
+ trigger: "hover",
+ inside: false
+ };
+ opts = util.extendAttributes("macTooltip", defaults, attrs);
+ showTip = function() {
+ var elementSize, offset, tip, tooltipSize;
+ if (disabled || !text || (tooltip != null)) {
+ return true;
+ }
+ tip = opts.inside ? element : angular.element(document.body);
+ removeTip(0);
+ tooltip = angular.element("<div class=\"mac-tooltip " + opts.direction + "\"><div class=\"tooltip-message\">" + text + "</div></div>");
+ tip.append(tooltip);
+ offset = opts.inside ? {
+ top: 0,
+ left: 0
+ } : element.offset();
+ elementSize = {
+ width: element.outerWidth(),
+ height: element.outerHeight()
+ };
+ tooltipSize = {
+ width: tooltip.outerWidth(),
+ height: tooltip.outerHeight()
+ };
+ switch (opts.direction) {
+ case "bottom":
+ case "top":
+ offset.left += elementSize.width / 2.0 - tooltipSize.width / 2.0;
+ break;
+ case "left":
+ case "right":
+ offset.top += elementSize.height / 2.0 - tooltipSize.height / 2.0;
+ }
+ switch (opts.direction) {
+ case "bottom":
+ offset.top += elementSize.height;
+ break;
+ case "top":
+ offset.top -= tooltipSize.height;
+ break;
+ case "left":
+ offset.left -= tooltipSize.width;
+ break;
+ case "right":
+ offset.left += elementSize.width;
+ }
+ offset.top = Math.max(0, offset.top);
+ offset.left = Math.max(0, offset.left);
+ angular.forEach(offset, function(value, key) {
+ if (!isNaN(+value) && angular.isNumber(+value)) {
+ value = "" + value + "px";
+ }
+ return tooltip.css(key, value);
+ });
+ tooltip.addClass("visible");
+ return true;
+ };
+ removeTip = function(delay) {
+ if (delay == null) {
+ delay = 100;
+ }
+ if ((tooltip != null) && (closeDelay == null)) {
+ tooltip.removeClass("visible");
+ closeDelay = $timeout(function() {
+ if (tooltip != null) {
+ tooltip.remove();
+ }
+ tooltip = null;
+ return closeDelay = null;
+ }, delay, false);
+ }
+ return true;
+ };
+ toggle = function() {
+ if (tooltip != null) {
+ return removeTip();
+ } else {
+ return showTip();
+ }
+ };
+ attrs.$observe("macTooltip", function(value) {
+ var _ref;
+ if (value != null) {
+ text = value;
+ if (!enabled) {
+ if ((_ref = opts.trigger) !== "hover" && _ref !== "click") {
+ throw "Invalid trigger";
+ }
+ switch (opts.trigger) {
+ case "click":
+ element.bind("click", toggle);
+ break;
+ case "hover":
+ element.bind("mouseenter", showTip);
+ element.bind("mouseleave click", function() {
+ return removeTip();
+ });
+ }
+ return enabled = true;
+ }
+ }
+ });
+ if (attrs.macTooltipDisabled != null) {
+ scope.$watch(attrs.macTooltipDisabled, function(value) {
+ return disabled = value;
+ });
+ }
+ return scope.$on("$destroy", function() {
+ if (tooltip != null) {
+ return removeTip(0);
+ }
+ });
+ }
+ };
+ }
+]);
+
+angular.module("Mac").filter("boolean", function() {
+ return function(boolean, trueString, falseString) {
+ if (trueString == null) {
+ trueString = "true";
+ }
+ if (falseString == null) {
+ falseString = "false";
+ }
+ if (boolean) {
+ return trueString;
+ } else {
+ return falseString;
+ }
+ };
+});
+
+angular.module("Mac").filter("true", function() {
+ return function(boolean, trueString) {
+ if (trueString == null) {
+ trueString = "true";
+ }
+ if (boolean) {
+ return trueString;
+ } else {
+ return "";
+ }
+ };
+});
+
+angular.module("Mac").filter("false", function() {
+ return function(boolean, falseString) {
+ if (falseString == null) {
+ falseString = "false";
+ }
+ if (boolean) {
+ return "";
+ } else {
+ return falseString;
+ }
+ };
+});
+
+
+/*
+@chalk overview
+@name List
+@description
+List filter. Use for converting arrays into a string
+
+@param {Array} list Array of items
+@param {String} separator String to separate each element of the array (default ,)
+@returns {String} Formatted string
+ */
+angular.module("Mac").filter("list", [
+ function() {
+ return function(list, separator) {
+ if (separator == null) {
+ separator = ", ";
+ }
+ return list.join(separator);
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Pluralize
+@description
+Pluralizes the given string. It's a simple proxy to the pluralize function on util.
+
+@param {String} string Noun to pluralize
+@param {Integer} count The numer of objects
+@param {Boolean} includeCount To include the number in formatted string
+@returns {String} Formatted plural
+ */
+angular.module("Mac").filter("pluralize", [
+ "util", function(util) {
+ return function(string, count, includeCount) {
+ if (includeCount == null) {
+ includeCount = true;
+ }
+ return util.pluralize(string, count, includeCount);
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Timestamp filter
+
+@description
+Takes in a unix timestamp and turns it into a human-readable relative time string, like "5
+minutes ago" or "just now".
+
+@param {Unix timestamp} time The time to format
+@returns {String} Formatted string
+ */
+angular.module("Mac").filter("timestamp", [
+ "util", function(util) {
+ var _createTimestamp;
+ _createTimestamp = function(count, noun) {
+ noun = util.pluralize(noun, count);
+ return "" + count + " " + noun + " ago";
+ };
+ return function(time) {
+ var currentTime, days, hours, minutes, months, secondsAgo, weeks, years;
+ time = +time;
+ currentTime = Math.round(Date.now() / 1000);
+ secondsAgo = currentTime - time;
+ if (secondsAgo < 45) {
+ return "just now";
+ } else if (secondsAgo < 120) {
+ return "about a minute ago";
+ } else {
+ years = Math.floor(secondsAgo / (365 * 24 * 60 * 60));
+ if (years > 0) {
+ return _createTimestamp(years, "year");
+ }
+ months = Math.floor(secondsAgo / (31 * 24 * 60 * 60));
+ if (months > 0) {
+ return _createTimestamp(months, "month");
+ }
+ weeks = Math.floor(secondsAgo / (7 * 24 * 60 * 60));
+ if (weeks > 0) {
+ return _createTimestamp(weeks, "week");
+ }
+ days = Math.floor(secondsAgo / (24 * 60 * 60));
+ if (days > 0) {
+ return _createTimestamp(days, "day");
+ }
+ hours = Math.floor(secondsAgo / (60 * 60));
+ if (hours > 0) {
+ return _createTimestamp(hours, "hour");
+ }
+ minutes = Math.floor(secondsAgo / 60);
+ if (minutes > 0) {
+ return _createTimestamp(minutes, "min");
+ }
+ return "" + secondsAgo + " seconds ago";
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Underscore string
+
+@description
+Proxy filter for calling underscore string function
+
+@param {String} string String to filter
+@param {String} fn Underscore function to call
+@param {Parameters} params Extra parameters to pass to Underscore string
+@returns {String} Formatted string
+ */
+var __slice = [].slice;
+
+angular.module("Mac").filter("underscoreString", function() {
+ return function() {
+ var fn, params, string;
+ string = arguments[0], fn = arguments[1], params = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ params.unshift(string);
+ return _.string[fn].apply(this, params);
+ };
+});
+
+
+/*
+@chalk overview
+@name Modal
+ */
+
+/*
+@chalk provider
+@name Modal Provider
+
+@description
+Configure modal options in config block
+
+@param {Object} defaults Modal default
+```js
+{
+ keyboard: false,
+ overlayClose: false,
+ resize: true,
+ position: true,
+ open: angular.noop,
+ topOffset: 20,
+ attributes: {},
+ beforeShow: angular.noop,
+ afterShow: angular.noop,
+ beforeHide: angular.noop,
+ afterHide: angular.noop
+}
+```
+ */
+
+/*
+@chalk service
+@name Modal Service
+
+@description
+There are multiple components used by modal.
+- A modal service is used to keep state of modal opened in the applications.
+- A modal element directive to define the modal dialog box
+- A modal attribute directive as a modal trigger
+
+@param {Function} show Show a modal based on the modal id
+- {String} id The id of the modal to open
+- {Object} triggerOptions Additional options to open modal
+
+@param {Function} resize Update the position and also the size of the modal
+- {Modal Object} modalObject The modal to reposition and resize (default opened modal)
+
+@param {Function} hide Hide currently opened modal
+- {Function} callback Callback after modal has been hidden
+
+@param {Function} bindingEvents Binding escape key or resize event
+- {String} action Either to bind or unbind events (default "bind")
+
+@param {Function} register Registering modal with the service
+- {String} id ID of the modal
+- {DOM element} element The modal element
+- {Object} options Additional options for the modal
+
+@param {Function} unregister Remove modal from modal service
+- {String} id ID of the modal to unregister
+
+@param {Function} clearWaiting Remove certain modal id from waiting list
+- {String} id ID of the modal
+ */
+angular.module("Mac").provider("modal", function() {
+ var defaults, registered;
+ this.registered = registered = {};
+ this.defaults = defaults = {
+ keyboard: false,
+ overlayClose: false,
+ resize: true,
+ position: true,
+ open: angular.noop,
+ topOffset: 20,
+ attributes: {},
+ beforeShow: angular.noop,
+ afterShow: angular.noop,
+ beforeHide: angular.noop,
+ afterHide: angular.noop
+ };
+ this.$get = [
+ "$animate", "$compile", "$controller", "$document", "$http", "$rootScope", "$templateCache", "keys", function($animate, $compile, $controller, $document, $http, $rootScope, $templateCache, keys) {
+ var escapeKeyHandler, resizeHandler, service;
+ escapeKeyHandler = function(event) {
+ var scope;
+ if (event.keyCode === keys.ESCAPE && service.opened) {
+ scope = service.opened.element.scope();
+ return scope.$apply(function() {
+ return service.hide();
+ });
+ }
+ };
+ resizeHandler = function() {
+ return service.resize();
+ };
+ service = {
+ registered: registered,
+ defaults: defaults,
+ waiting: null,
+ opened: null,
+ modalTemplate: "<div class=\"mac-modal-overlay\">\n <div class=\"mac-modal\">\n <a mac-modal-close class=\"mac-close-modal\"></a>\n <div class=\"mac-modal-content-wrapper\"></div>\n </div>\n</div>",
+ show: function(id, triggerOptions) {
+ var modalObject, options, path, renderModal, showModal, showOptions, template;
+ if (triggerOptions == null) {
+ triggerOptions = {};
+ }
+ if ((this.registered[id] != null) && (this.opened != null)) {
+ return this.hide();
+ } else if (this.registered[id] != null) {
+ modalObject = this.registered[id];
+ options = modalObject.options;
+ showOptions = {};
+ angular.extend(showOptions, options, triggerOptions);
+ showModal = (function(_this) {
+ return function(element) {
+ showOptions.beforeShow(element.scope());
+ return $animate.addClass(element, "visible").then(function() {
+ _this.opened = {
+ id: id,
+ element: element,
+ options: showOptions
+ };
+ _this.resize(_this.opened);
+ _this.bindingEvents();
+ showOptions.open(element.scope());
+ showOptions.afterShow(element.scope());
+ $rootScope.$broadcast("modalWasShown", id);
+ return _this.clearWaiting();
+ });
+ };
+ })(this);
+ if (showOptions.moduleMethod != null) {
+ renderModal = (function(_this) {
+ return function(template) {
+ var element, viewScope, wrapper;
+ if (angular.isScope(showOptions.scope)) {
+ viewScope = showOptions.scope;
+ } else {
+ viewScope = $rootScope.$new(true);
+ if (angular.isObject(showOptions.scope)) {
+ angular.extend(viewScope, showOptions.scope);
+ }
+ }
+ angular.extend(showOptions.attributes, {
+ id: id
+ });
+ element = angular.element(_this.modalTemplate).attr(showOptions.attributes);
+ wrapper = angular.element(element[0].getElementsByClassName("mac-modal-content-wrapper"));
+ wrapper.html(template);
+ if (showOptions.overlayClose) {
+ element.bind("click", function($event) {
+ if (angular.element($event.target).hasClass("mac-modal-overlay")) {
+ return viewScope.$apply(function() {
+ return _this.hide();
+ });
+ }
+ });
+ }
+ if (showOptions.controller) {
+ $controller(showOptions.controller, {
+ $scope: viewScope,
+ $element: element,
+ macModalOptions: showOptions
+ });
+ }
+ $animate.enter(element, angular.element(document.body));
+ $compile(element)(viewScope);
+ return showModal(element);
+ };
+ })(this);
+ if ((path = showOptions.templateUrl)) {
+ template = $templateCache.get(path);
+ if (template) {
+ return renderModal(template);
+ } else {
+ return $http.get(path).then(function(resp) {
+ $templateCache.put(path, resp.data);
+ return renderModal(resp.data);
+ }, function() {
+ throw Error("Failed to load template: " + path);
+ });
+ }
+ } else if ((template = showOptions.template)) {
+ return renderModal(template);
+ }
+ } else if (modalObject.element != null) {
+ return showModal(modalObject.element);
+ }
+ } else {
+ return this.waiting = {
+ id: id,
+ options: triggerOptions
+ };
+ }
+ },
+ resize: function(modalObject) {
+ var css, element, height, modal, options, width;
+ if (modalObject == null) {
+ modalObject = this.opened;
+ }
+ if (modalObject == null) {
+ return;
+ }
+ element = modalObject.element;
+ options = modalObject.options;
+ if (!options.position) {
+ return;
+ }
+ modal = angular.element(element[0].querySelector(".mac-modal"));
+ height = modal.outerHeight();
+ width = modal.outerWidth();
+ css = angular.element(window).height() > height ? {
+ marginTop: -height / 2
+ } : {
+ top: options.topOffset
+ };
+ css.marginLeft = -width / 2;
+ return angular.forEach(css, function(value, key) {
+ if (!isNaN(+value) && angular.isNumber(+value)) {
+ value = "" + value + "px";
+ }
+ return modal.css(key, value);
+ });
+ },
+ hide: function() {
+ var element, id, options, self, _ref;
+ if (this.opened == null) {
+ return;
+ }
+ _ref = this.opened, id = _ref.id, options = _ref.options, element = _ref.element;
+ options.beforeHide(element.scope());
+ self = this;
+ return $animate.removeClass(element, "visible").then(function() {
+ var modal;
+ self.bindingEvents("unbind");
+ self.opened = null;
+ if (options.moduleMethod) {
+ if (!angular.isScope(options.scope)) {
+ element.scope().$destroy();
+ }
+ $animate.leave(element);
+ } else {
+ modal = element[0].querySelector(".mac-modal");
+ modal.removeAttribute("style");
+ }
+ options.afterHide(element.scope());
+ return $rootScope.$broadcast("modalWasHidden", id);
+ });
+ },
+ bindingEvents: function(action) {
+ var options;
+ if (action == null) {
+ action = "bind";
+ }
+ if (!((action === "bind" || action === "unbind") && (this.opened != null))) {
+ return;
+ }
+ options = this.opened.options;
+ if (options.keyboard) {
+ $document[action]("keydown", escapeKeyHandler);
+ }
+ if (options.resize) {
+ return angular.element(window)[action]("resize", resizeHandler);
+ }
+ },
+ register: function(id, element, options) {
+ var modalOpts;
+ if (this.registered[id] != null) {
+ throw new Error("Modal " + id + " already registered");
+ }
+ modalOpts = {};
+ angular.extend(modalOpts, defaults, options);
+ this.registered[id] = {
+ id: id,
+ element: element,
+ options: modalOpts
+ };
+ if ((this.waiting != null) && this.waiting.id === id) {
+ return this.show(id, this.waiting.options);
+ }
+ },
+ unregister: function(id) {
+ var _ref;
+ if (this.registered[id] == null) {
+ throw new Error("Modal " + id + " is not registered");
+ }
+ if (((_ref = this.opened) != null ? _ref.id : void 0) === id) {
+ this.hide();
+ }
+ this.clearWaiting(id);
+ return delete this.registered[id];
+ },
+ clearWaiting: function(id) {
+ var _ref;
+ if ((id != null) && ((_ref = this.waiting) != null ? _ref.id : void 0) !== id) {
+ return;
+ }
+ return this.waiting = null;
+ }
+ };
+ return service;
+ }
+ ];
+}).config([
+ "modalProvider", function(modal) {
+ return angular.module("Mac").modal = function(id, modalOptions) {
+ var options;
+ if (modal.registered[id] == null) {
+ options = {};
+ angular.extend(options, modal.defaults, modalOptions, {
+ moduleMethod: true
+ });
+ return modal.registered[id] = {
+ id: id,
+ options: options
+ };
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Popover
+ */
+
+/*
+@chalk provider
+@name Popover Provider
+
+@description
+Configurate popover options in config block.
+
+@param {Object} defaults Popover defaults
+```js
+{
+ fixed: false,
+ childPopover: false,
+ offsetY: 0,
+ offsetX: 0,
+ trigger: "click"
+}
+```
+
+@param {Object} popoverDefaults Popover trigger defaults
+```js
+{
+ footer: false,
+ header: false,
+ title: "",
+ direction: "above left"
+}
+```
+
+@param {String} template Popover template
+```js
+"<div class=\"mac-popover\" ng-class=\"macPopoverClasses\">
+ <div class=\"tip\"></div>
+ <div class=\"popover-header\">
+ <div class=\"title\">{{macPopoverTitle}}</div>
+ </div>
+ <div mac-popover-fill-content></div>
+</div>";
+```
+ */
+
+/*
+@chalk service
+@name Popover Service
+
+@description
+Popover service to keep state of opened popover. Allowing user to hide certain
+or all popovers
+
+@param {Array} popoverList The popover that's currently being shown
+
+@param {Array} registered Object storing all the registered popover DOM elements
+
+@param {Function} last Get data of the last popover
+- Returns {Object} The last opened popover
+
+@param {Function} register Register a popover with an id and an element
+- {String} id Popover id
+- {DOM Element} element Popover element
+- Returns {Bool} If the id already existed
+
+@param {Function} unregister Remove id and element from registered list of popover
+- {String} id Popover id
+- Returns {Bool} If the id exist
+
+@param {Function} add Add a new popover to opened list
+- {String} id Popover id
+- {DOM Element} popover Popover DOM element
+- {DOM Element} element Trigger DOM element
+- {Object} options Additional options
+- Returns {Object} The new popover object
+
+@param {Function} pop Get and remove the last popover from list
+- Returns {Object} Last element from popoverList
+
+@param {Function} show Show and position a registered popover
+- {String} id Popover id
+- {DOM Element} element Element that trigger the popover
+- {Object} options Additional options for popover
+
+@param {Function} getById Get opened popover object by id
+- {String} id Popover id
+- Returns {Object} Opened popover object
+
+@param {Function} resize Update size and position of an opened popover
+- {Object|String} popoverObj Support multiple type input:
+ - Object: One of the popover objects in popoverList
+ - String: Popover ID
+
+@param {Function} hide Hide a certain popover. If no selector is provided, the
+last opened popover is hidden
+- {DOM Element|String} selector Support multiple type input:
+ - DOM Element: Popover trigger element
+ - String: Popover ID
+- {Function} callback Callback after popover is hidden
+
+@param {Function} hideAll Hide all popovers
+ */
+angular.module("Mac").provider("popover", function() {
+ var defaults, popoverDefaults, popoverTemplate, registered;
+ this.registered = registered = {};
+ this.defaults = defaults = {
+ fixed: false,
+ childPopover: false,
+ offsetY: 0,
+ offsetX: 0,
+ trigger: "click"
+ };
+ this.popoverDefaults = popoverDefaults = {
+ footer: false,
+ header: false,
+ title: "",
+ direction: "above left"
+ };
+
+ /*
+ @name template
+ @description
+ Popover template
+ */
+ this.template = popoverTemplate = "<div class=\"mac-popover\" ng-class=\"macPopoverClasses\">\n <div class=\"tip\"></div>\n <div class=\"popover-header\">\n <div class=\"title\">{{macPopoverTitle}}</div>\n </div>\n <div mac-popover-fill-content></div>\n</div>";
+ this.$get = [
+ "$animate", "$compile", "$controller", "$http", "$rootScope", "$templateCache", "$timeout", function($animate, $compile, $controller, $http, $rootScope, $templateCache, $timeout) {
+ var service;
+ service = {
+ popoverList: [],
+ registered: registered,
+ defaults: defaults,
+ popoverDefaults: popoverDefaults,
+ template: popoverTemplate,
+ last: function() {
+ return this.popoverList[this.popoverList.length - 1];
+ },
+ register: function(id, options) {
+ var exist;
+ if (!(exist = this.registered[id] != null)) {
+ this.registered[id] = options;
+ }
+ return !exist;
+ },
+ unregister: function(id) {
+ var exist;
+ if (exist = this.registered[id] != null) {
+ delete this.registered[id];
+ }
+ return exist;
+ },
+ add: function(id, popover, element, options) {
+ var newObject;
+ newObject = {
+ id: id,
+ popover: popover,
+ element: element,
+ options: options
+ };
+ this.popoverList.push(newObject);
+ return newObject;
+ },
+ pop: function() {
+ return this.popoverList.pop();
+ },
+ show: function(id, element, options) {
+ var addPopover, popoverOptions;
+ if (options == null) {
+ options = {};
+ }
+ popoverOptions = this.registered[id];
+ if (!popoverOptions) {
+ return false;
+ }
+ addPopover = function() {
+ var path, showPopover, template;
+ showPopover = function(template) {
+ var popover, popoverObj, viewScope;
+ if (angular.isScope(options.scope)) {
+ viewScope = options.scope.$new();
+ } else {
+ viewScope = $rootScope.$new(true);
+ if (angular.isObject(options.scope)) {
+ angular.extend(viewScope, options.scope);
+ }
+ }
+ if (popoverOptions.refreshOn) {
+ viewScope.$on(popoverOptions.refreshOn, function() {
+ return service.resize(id);
+ });
+ }
+ if (popoverOptions.controller) {
+ $controller(popoverOptions.controller, {
+ $scope: viewScope
+ });
+ }
+ angular.extend(viewScope, {
+ macPopoverClasses: {
+ footer: popoverOptions.footer || false,
+ header: popoverOptions.header || !!popoverOptions.title || false,
+ fixed: popoverOptions.fixed || false
+ },
+ macPopoverTitle: popoverOptions.title || "",
+ macPopoverTemplate: template
+ });
+ popover = $compile(popoverTemplate)(viewScope);
+ popover.attr({
+ id: id,
+ direction: popoverOptions.direction || "below left"
+ });
+ popoverObj = service.add(id, popover, element, options);
+ $animate.addClass(element, "active");
+ $rootScope.$broadcast("popoverWasShown", id);
+ return $animate.enter(popover, angular.element(document.body)).then(function() {
+ return service.resize(popoverObj);
+ });
+ };
+ if ((template = popoverOptions.template)) {
+ return showPopover(template);
+ } else if ((path = popoverOptions.templateUrl)) {
+ template = $templateCache.get(path);
+ if (template) {
+ return showPopover(template);
+ } else {
+ return $http.get(path).then(function(resp) {
+ $templateCache.put(path, resp.data);
+ return showPopover(resp.data);
+ }, function() {
+ throw new Error('Failed to load template: #{path}');
+ });
+ }
+ }
+ };
+ if (service.popoverList.length && !!!options.childPopover) {
+ service.hide(addPopover);
+ } else {
+ addPopover();
+ }
+ return true;
+ },
+ getById: function(id, element) {
+ var item, sameTrigger, _i, _len, _ref;
+ _ref = this.popoverList;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ sameTrigger = (element == null) || item.element === element;
+ if (item.id === id && sameTrigger) {
+ return item;
+ }
+ }
+ },
+ resize: function(popoverObj) {
+ var $window, action, current, currentPopover, diff, left, leftScroll, offset, options, position, relative, relativeElement, setOverflowPosition, top, topScroll, updateOffset;
+ if (angular.isString(popoverObj)) {
+ popoverObj = service.getById(popoverObj);
+ }
+ if (popoverObj == null) {
+ return;
+ }
+ currentPopover = popoverObj.popover;
+ relativeElement = popoverObj.element;
+ options = popoverObj.options;
+ $window = angular.element(window);
+ offset = relativeElement.offset();
+ if (options.fixed) {
+ offset.top = relativeElement.position().top;
+ }
+ relative = {
+ height: relativeElement.outerHeight(),
+ width: relativeElement.outerWidth()
+ };
+ current = {
+ height: currentPopover.outerHeight(),
+ width: currentPopover.outerWidth()
+ };
+ top = 0;
+ left = 0;
+ position = (currentPopover.attr("direction") || "top left").trim();
+ setOverflowPosition = function(offset) {
+ var tip, tipOffset;
+ if (offset == null) {
+ offset = 0;
+ }
+ tip = angular.element(currentPopover[0].getElementsByClassName("tip"));
+ top -= offset;
+ tipOffset = +tip.css("margin-top").replace("px", "");
+ return tip.css("margin-top", tipOffset + offset);
+ };
+ updateOffset = function() {
+ switch (position) {
+ case "above left":
+ top = -(current.height + 10);
+ return left = -25 + relative.width / 2;
+ case "above right":
+ top = -(current.height + 10);
+ return left = 25 + relative.width / 2 - current.width;
+ case "below left":
+ top = relative.height + 10;
+ return left = -25 + relative.width / 2;
+ case "below right":
+ top = relative.height + 10;
+ return left = 25 + relative.width / 2 - current.width;
+ case "middle right":
+ top = relative.height / 2 - current.height / 2;
+ return left = relative.width + 10;
+ case "middle left":
+ top = relative.height / 2 - current.height / 2;
+ return left = -(current.width + 10);
+ }
+ };
+ updateOffset();
+ topScroll = options.fixed ? 0 : $window.scrollTop();
+ leftScroll = options.fixed ? 0 : $window.scrollLeft();
+ action = {};
+ if (position.indexOf("middle") === -1) {
+ if (offset.top + top - topScroll < 0) {
+ action = {
+ remove: "above",
+ add: "below"
+ };
+ } else if (offset.top + top + current.height - topScroll > $window.height()) {
+ action = {
+ remove: "below",
+ add: "above"
+ };
+ }
+ } else {
+ if ((diff = offset.top + top - topScroll) < 0) {
+ setOverflowPosition(diff);
+ } else if ((diff = offset.top + top + currentPopover.outerHeight() - topScroll - $window.height()) > 0) {
+ setOverflowPosition(diff);
+ }
+ }
+ if (action.remove && action.add) {
+ position = position.replace(action.remove, action.add);
+ }
+ action = {};
+ if (offset.left + left - leftScroll < 0) {
+ action = {
+ remove: "right",
+ add: "left"
+ };
+ } else if (offset.left + left + currentPopover.outerWidth() - leftScroll > $window.width()) {
+ action = {
+ remove: "left",
+ add: "right"
+ };
+ }
+ if (action.remove && action.add) {
+ position = position.replace(action.remove, action.add);
+ }
+ updateOffset();
+ offset.top += top;
+ offset.left += left;
+ if (options.offsetX != null) {
+ offset.left += options.offsetX;
+ }
+ if (options.offsetY != null) {
+ offset.top += options.offsetY;
+ }
+ angular.forEach(offset, function(value, key) {
+ if (!isNaN(+value)) {
+ value = "" + value + "px";
+ }
+ return currentPopover.css(key, value);
+ });
+ return currentPopover.addClass("visible " + position);
+ },
+ hide: function(selector, callback) {
+ var comparator, i, index, popoverObj, removeScope, _i, _ref;
+ if (!this.popoverList.length) {
+ return typeof callback === "function" ? callback() : void 0;
+ }
+ if (angular.isFunction(selector)) {
+ callback = selector;
+ selector = null;
+ }
+ if (selector != null) {
+ comparator = angular.isString(selector) ? function(item) {
+ return item.id === selector;
+ } : angular.isElement(selector) ? function(item) {
+ return item.element === selector;
+ } : void 0;
+ index = -1;
+ for (i = _i = _ref = this.popoverList.length - 1; _i >= 0; i = _i += -1) {
+ if (!(comparator(this.popoverList[i]))) {
+ continue;
+ }
+ popoverObj = this.popoverList[i];
+ index = i;
+ break;
+ }
+ if (index > -1) {
+ this.popoverList.splice(index, 1);
+ }
+ } else {
+ popoverObj = this.pop();
+ }
+ if (popoverObj == null) {
+ return;
+ }
+ $rootScope.$broadcast("popoverBeforeHide", popoverObj.id);
+ $animate.removeClass(popoverObj.element, "active");
+ removeScope = popoverObj.popover.scope();
+ return $animate.leave(popoverObj.popover).then(function() {
+ $rootScope.$broadcast("popoverWasHidden", popoverObj.id);
+ removeScope.$destroy();
+ return typeof callback === "function" ? callback() : void 0;
+ });
+ },
+ hideAll: function() {
+ while (this.popoverList.length) {
+ this.hide();
+ }
+ }
+ };
+ return service;
+ }
+ ];
+}).config([
+ "popoverProvider", function(popoverProvider) {
+ return angular.module("Mac").popover = function(name, options) {
+ var opts;
+ if (popoverProvider.registered[name] == null) {
+ opts = {};
+ angular.extend(opts, popoverProvider.popoverDefaults, options, {
+ id: name
+ });
+ return popoverProvider.registered[name] = opts;
+ }
+ };
+ }
+]);
+
+
+/*
+@chalk overview
+@name Scroll Spy Service
+
+@description
+There are multiple components used by scrollspy
+- Scrollspy service is used to keep track of all and active anchors
+- Multiple directives including:
+- mac-scroll-spy - Element to spy scroll event
+- mac-scroll-spy-anchor - Section in element spying on
+- mac-scroll-spy-target - Element to highlight, most likely a nav item
+
+Scrollspy defaults:
+offset - 0
+
+@param {Function} register Register an anchor with the service
+- {String} id ID of the anchor
+- {DOM Element} element Element to spy on
+
+@param {Function} unregister Remove anchor from service
+- {String} id ID of the anchor
+
+@param {Function} setActive Set active anchor and fire all listeners
+- {Object} anchor Anchor object
+
+@param {Function} addListener Add listener when active is set
+- {Function} fn Callback function
+
+@param {Function} removeListener Remove listener
+- {Function} fn Callback function
+ */
+angular.module("Mac").service("scrollSpy", [
+ function() {
+ return {
+ registered: [],
+ active: {},
+ listeners: [],
+ register: function(id, element) {
+ var anchor, i, registered, top, _i, _len, _ref;
+ registered = false;
+ top = element.offset().top;
+ _ref = this.registered;
+ for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
+ anchor = _ref[i];
+ if (!(anchor.id === id)) {
+ continue;
+ }
+ this.registered[i] = {
+ id: id,
+ element: element,
+ top: top
+ };
+ registered = true;
+ break;
+ }
+ if (!registered) {
+ this.registered.push({
+ id: id,
+ element: element,
+ top: top
+ });
+ }
+ return this.registered.sort(function(a, b) {
+ if (a.top > b.top) {
+ return 1;
+ } else if (a.top < b.top) {
+ return -1;
+ }
+ return 0;
+ });
+ },
+ unregister: function(id) {
+ var anchor, i, _i, _len, _ref, _ref1, _results;
+ _ref = this.registered;
+ _results = [];
+ for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
+ anchor = _ref[i];
+ if (!(anchor.id === id)) {
+ continue;
+ }
+ [].splice.apply(this.registered, [i, i - i + 1].concat(_ref1 = [])), _ref1;
+ break;
+ }
+ return _results;
+ },
+ last: function() {
+ return this.registered[this.registered.length - 1];
+ },
+ setActive: function(anchor) {
+ var listener, _i, _len, _ref, _results;
+ this.active = anchor;
+ _ref = this.listeners;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ listener = _ref[_i];
+ _results.push(listener(anchor));
+ }
+ return _results;
+ },
+ addListener: function(fn) {
+ return this.listeners.push(fn);
+ },
+ removeListener: function(fn) {
+ var index, _ref;
+ index = this.listeners.indexOf(fn);
+ if (index !== -1) {
+ return ([].splice.apply(this.listeners, [index, index - index + 1].concat(_ref = [])), _ref);
+ }
+ }
+ };
+ }
+]).constant("scrollSpyDefaults", {
+ offset: 0
+});
+
+var __hasProp = {}.hasOwnProperty;
+
+angular.module("Mac.Util", []).factory("util", [
+ "$filter", function($filter) {
+ return {
+ _inflectionConstants: {
+ uncountables: ["sheep", "fish", "moose", "series", "species", "money", "rice", "information", "info", "equipment", "min"],
+ irregulars: {
+ child: "children",
+ man: "men",
+ woman: "women",
+ person: "people",
+ ox: "oxen",
+ goose: "geese"
+ },
+ pluralizers: [[/(quiz)$/i, "$1zes"], [/([m|l])ouse$/i, "$1ice"], [/(matr|vert|ind)(ix|ex)$/i, "$1ices"], [/(x|ch|ss|sh)$/i, "$1es"], [/([^aeiouy]|qu)y$/i, "$1ies"], [/(?:([^f])fe|([lr])f)$/i, "$1$2ves"], [/sis$/i, "ses"], [/([ti])um$/i, "$1a"], [/(buffal|tomat)o$/i, "$1oes"], [/(bu)s$/i, "$1ses"], [/(alias|status)$/i, "$1es"], [/(octop|vir)us$/i, "$1i"], [/(ax|test)is$/i, "$1es"], [/x$/i, "xes"], [/s$/i, "s"], [/$/, "s"]]
+ },
+
+ /*
+ @name pluralize
+ @description
+ Pluralize string based on the count
+
+ @param {String} string String to pluralize (default "")
+ @param {Integer} count Object counts
+ @param {Boolean} includeCount Include the number or not (default false)
+
+ @returns {String} Pluralized string based on the count
+ */
+ pluralize: function(string, count, includeCount) {
+ var irregulars, isUppercase, lowercaseWord, pluralizedString, pluralizedWord, pluralizer, pluralizers, uncountables, word, _i, _len, _ref;
+ if (string == null) {
+ string = "";
+ }
+ if (includeCount == null) {
+ includeCount = false;
+ }
+ if (!angular.isString(string) || this.trim(string).length === 0) {
+ return string;
+ }
+ if (includeCount && isNaN(+count)) {
+ return "";
+ }
+ if (count == null) {
+ count = 2;
+ }
+ _ref = this._inflectionConstants, pluralizers = _ref.pluralizers, uncountables = _ref.uncountables, irregulars = _ref.irregulars;
+ word = string.split(/\s/).pop();
+ isUppercase = word.toUpperCase() === word;
+ lowercaseWord = word.toLowerCase();
+ pluralizedWord = count === 1 || uncountables.indexOf(lowercaseWord) >= 0 ? word : null;
+ if (pluralizedWord == null) {
+ if (irregulars[lowercaseWord] != null) {
+ pluralizedWord = irregulars[lowercaseWord];
+ }
+ }
+ if (pluralizedWord == null) {
+ for (_i = 0, _len = pluralizers.length; _i < _len; _i++) {
+ pluralizer = pluralizers[_i];
+ if (!(pluralizer[0].test(lowercaseWord))) {
+ continue;
+ }
+ pluralizedWord = word.replace(pluralizer[0], pluralizer[1]);
+ break;
+ }
+ }
+ pluralizedWord || (pluralizedWord = word);
+ if (isUppercase) {
+ pluralizedWord = pluralizedWord.toUpperCase();
+ }
+ pluralizedString = string.slice(0, -word.length) + pluralizedWord;
+ if (includeCount) {
+ return "" + ($filter("number")(count)) + " " + pluralizedString;
+ } else {
+ return pluralizedString;
+ }
+ },
+ trim: function(string) {
+ var str;
+ str = String(string) || "";
+ if (String.prototype.trim != null) {
+ return str.trim();
+ } else {
+ return str.replace(/^\s+|\s+$/gm, "");
+ }
+ },
+ capitalize: function(string) {
+ var str;
+ str = String(string) || "";
+ return str.charAt(0).toUpperCase() + str.substring(1);
+ },
+ uncapitalize: function(string) {
+ var str;
+ str = String(string) || "";
+ return str.charAt(0).toLowerCase() + str.substring(1);
+ },
+ toCamelCase: function(string) {
+ if (string == null) {
+ string = "";
+ }
+ return this.trim(string).replace(/[-_\s]+(.)?/g, function(match, c) {
+ return c.toUpperCase();
+ });
+ },
+ toSnakeCase: function(string) {
+ if (string == null) {
+ string = "";
+ }
+ return this.trim(string).replace(/([a-z\d])([A-Z]+)/g, "$1_$2").replace(/[-\s]+/g, "_").toLowerCase();
+ },
+ convertKeysToCamelCase: function(object) {
+ var key, result, value;
+ result = {};
+ for (key in object) {
+ if (!__hasProp.call(object, key)) continue;
+ value = object[key];
+ key = this.toCamelCase(key);
+ if (typeof value === "object" && (value != null ? value.constructor : void 0) !== Array) {
+ value = this.convertKeysToCamelCase(value);
+ }
+ result[key] = value;
+ }
+ return result;
+ },
+ convertKeysToSnakeCase: function(object) {
+ var key, result, value;
+ result = {};
+ for (key in object) {
+ if (!__hasProp.call(object, key)) continue;
+ value = object[key];
+ key = this.toSnakeCase(key);
+ if (typeof value === "object" && (value != null ? value.constructor : void 0) !== Array) {
+ value = this.convertKeysToSnakeCase(value);
+ }
+ result[key] = value;
+ }
+ return result;
+ },
+ pyth: function(a, b) {
+ return Math.sqrt(a * a + b * b);
+ },
+ degrees: function(radian) {
+ return (radian * 180) / Math.PI;
+ },
+ radian: function(degrees) {
+ return (degrees * Math.PI) / 180;
+ },
+ hex2rgb: function(hex) {
+ var color, rgb, value;
+ if (hex.indexOf('#') === 0) {
+ hex = hex.substring(1);
+ }
+ hex = hex.toLowerCase();
+ rgb = {};
+ if (hex.length === 3) {
+ rgb.r = hex.charAt(0) + hex.charAt(0);
+ rgb.g = hex.charAt(1) + hex.charAt(1);
+ rgb.b = hex.charAt(2) + hex.charAt(2);
+ } else {
+ rgb.r = hex.substring(0, 2);
+ rgb.g = hex.substring(2, 4);
+ rgb.b = hex.substring(4);
+ }
+ for (color in rgb) {
+ value = rgb[color];
+ rgb[color] = parseInt(value, 16);
+ }
+ return rgb;
+ },
+ timeRegex: /^(0?[1-9]|1[0-2]):([0-5][0-9])[\s]([AP]M)$/,
+ _urlRegex: /(?:(http[s]?):\/\/)?(?:(www|[\d\w\-]+)\.)?([\d\w\-]+)\.([A-Za-z]{2,6})(:[\d]*)?([:\/?#\[\]@!$&'()*+,;=\w\d-._~%\\]*)?/i,
+ _emailRegex: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
+ validateUrl: function(url) {
+ var match;
+ match = this._urlRegex.exec(url);
+ if (match != null) {
+ match = {
+ url: match[0],
+ protocol: match[1] || "http",
+ subdomain: match[2],
+ name: match[3],
+ domain: match[4],
+ port: match[5],
+ path: match[6] || "/"
+ };
+ match["url"] = match.url;
+ }
+ return match;
+ },
+ validateEmail: function(email) {
+ return this._emailRegex.test(email);
+ },
+ getQueryString: function(url, name) {
+ var regex, regexS, results;
+ if (name == null) {
+ name = "";
+ }
+ name = name.replace(/[[]/, "\[").replace(/[]]/, "\]");
+ regexS = "[\?&]" + name + "=([^&#]*)";
+ regex = new RegExp(regexS);
+ results = regex.exec(url);
+ if (results != null) {
+ return results[1];
+ } else {
+ return "";
+ }
+ },
+ parseUrlPath: function(fullPath) {
+ var path, pathComponents, queries, queryString, queryStrings, urlComponents, values, verb, _i, _len, _ref;
+ urlComponents = fullPath.split("?");
+ pathComponents = urlComponents[0].split("/");
+ path = pathComponents.slice(0, pathComponents.length - 1).join("/");
+ verb = pathComponents[pathComponents.length - 1];
+ queries = {};
+ if (urlComponents.length > 1) {
+ queryStrings = urlComponents[urlComponents.length - 1];
+ _ref = queryStrings.split("&");
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ queryString = _ref[_i];
+ values = queryString.split("=");
+ queries[values[0]] = values[1] != null ? values[1] : "";
+ }
+ }
+ return {
+ fullPath: fullPath,
+ path: path,
+ pathComponents: pathComponents,
+ verb: verb,
+ queries: queries
+ };
+ },
+ extendAttributes: function(prefix, defaults, attributes) {
+ var altKey, key, macKey, output, value, _ref, _ref1;
+ if (prefix == null) {
+ prefix = "";
+ }
+ output = {};
+ for (key in defaults) {
+ if (!__hasProp.call(defaults, key)) continue;
+ value = defaults[key];
+ altKey = prefix ? this.capitalize(key) : key;
+ macKey = "" + prefix + altKey;
+ output[key] = attributes[macKey] != null ? attributes[macKey] || true : value;
+ if ((_ref = output[key]) === "true" || _ref === "false") {
+ output[key] = output[key] === "true";
+ } else if (((_ref1 = output[key]) != null ? _ref1.length : void 0) > 0 && !isNaN(+output[key])) {
+ output[key] = +output[key];
+ }
+ }
+ return output;
+ }
+ };
+ }
+]);
+
+})(window, window.angular); \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.min.js b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.min.js
new file mode 100644
index 00000000..1603552f
--- /dev/null
+++ b/openk-platform/openk-theme/src/main/webapp/js/macgyver-0.6.1/macgyver.min.js
@@ -0,0 +1,2 @@
+!function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n;m=["Mac.Util"];try{b.module("ngAnimate"),m.push("ngAnimate")}catch(o){}b.module("Mac",m),e=["Top","Right","Bottom","Left"],d=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,n=new RegExp("^("+d+")(?!px)[a-z%]+$","i"),g=function(b){return a.getComputedStyle(b,null)},k=function(a){return a&&a.document&&a.location&&a.alert&&a.setInterval},j=function(a){return a&&null!=a.$evalAsync&&null!=a.$watch},b.isScope=j,i=function(a){return k(a)?a:9===a.nodeType&&a.defaultView},c=function(a,b,c,d,f){var g,h,i,j;if(c===(d?"border":"content"))return 0;for(i=0,h="Width"===b?1:0,g=j=h;3>=j;g=j+=2)"margin"===c&&(i+=parseFloat(f[""+c+e[g]])),d?("content"===c&&(i-=parseFloat(f["padding"+e[g]])),"margin"!==c&&(i-=parseFloat(f["border"+e[g]]))):(i+=parseFloat(f["padding"+e[g]]),"padding"!==c&&(i+=parseFloat(f["border"+e+"Width"])));return i},h=function(a,b,d){return function(e){var f,h,i,j,l,m,o,p;if(f=function(){switch(b){case"inner":return"padding";case"outer":return"";default:return"content"}}(),i=f||(e===!0?"margin":"border"),k(d))return d.document.documentElement["client"+a];if(9===d.nodeType)return h=d.documentElement,Math.max(d.body["scroll"+a],h["scroll"+a],d.body["offset"+a],h["offset"+a],h["client"+a]);if(p=!0,m=g(d),l=a.toLowerCase(),o="Height"===a?d.offsetHeight:d.offsetWidth,j="border-box"===d.style.boxSizing,0>=o||null===o){if(o=m[l],(0>o||null===o)&&(o=d.style[l]),n.test(o))return o;p=j,o=parseFloat(o)||0}return o+c(d,a,i||(j?"border":"content"),p,m)}},l={height:function(a){return h("Height","",a)()},width:function(a){return h("Width","",a)()},outerHeight:function(a,b){return h("Height","outer",a)(b)},outerWidth:function(a,b){return h("Width","outer",a)(b)},offset:function(a){var b,c,d,e;return b={top:0,left:0},(c=a&&a.ownerDocument)?(d=c.documentElement,null!=a.getBoundingClientRect&&(b=a.getBoundingClientRect()),e=i(c),{top:b.top+e.pageYOffset-d.clientTop,left:b.left+e.pageXOffset-d.clientLeft}):void 0},scrollTop:function(b,c){var d;return d=i(b),null==c?d?d.pageYOffset:b.scrollTop:d?d.scrollTo(a.pageYOffset,c):b.scrollTop=c},scrollLeft:function(b,c){var d;return d=i(b),null==c?d?d.pageXOffset:b.scrollLeft:d?d.scrollTo(a.pageXOffset,c):b.scrollLeft=c}},f=function(){var c;if(null==a.jQuery||null==b.element.prototype.offset)return c=b.element,b.forEach(l,function(a,b){return c.prototype[b]=function(b,c){return this.length?a(this[0],b,c):void 0}})},f(),b.module("Mac").directive("macAffix",["$document","$window",function(a,c){return{link:function(d,e,f){var g,h,i,j,k,l,m,n,o,p;return g={top:0,bottom:0,disabled:!1,classes:"affix affix-top affix-bottom"},k={top:g.top,bottom:g.bottom},h=g.disabled,j=null,o=null,l=null,p=b.element(c),n=function(a,b,c){return null==c&&(c=!1),c&&null==b&&(b=g[a]),null==b||isNaN(+b)?void 0:k[a]=+b},null!=f.macAffixTop&&(n("top",d.$eval(f.macAffixTop),!0),d.$watch(f.macAffixTop,function(a){return n("top",a)})),null!=f.macAffixBottom&&(n("bottom",d.$eval(f.macAffixBottom),!0),d.$watch(f.macAffixBottom,function(a){return n("bottom",a)})),i=function(){var b;return null!=l?l:(e.removeClass(g.classes).addClass("affix"),b=a.height(),l=b-e.outerHeight()-k.bottom)},m=function(){var b,c,d,f,h,l;if(!(e[0].offsetHeight<=0&&e[0].offsetWidth<=0)&&(f=e.offset(),l=p.scrollTop(),h=a.height(),d=e.outerHeight(),b=null!=o&&o>=l?!1:null!=k.bottom&&l>h-d-k.bottom?"bottom":null!=k.top&&l<=k.top?"top":!1,b!==j))return o&&e.css("top",""),j=b,o="bottom"===b?i():null,e.removeClass(g.classes).addClass("affix"+(b?"-"+b:"")),"bottom"===b&&(c=e.offset(),e.css("top",o-c.top)),!0},null!=f.macAffixDisabled&&(h=d.$eval(f.macAffixDisabled)||g.disabled,d.$watch(f.macAffixDisabled,function(a){var b;if(null!=a&&a!==h)return h=a,b=a?"unbind":"bind",p[b]("scroll",m),h?(j=null,o=null,e.css("top","").removeClass(g.classes)):m()})),h||p.bind("scroll",m),d.$on("refresh-mac-affix",function(){var a;return a=e.offset()}),d.$on("$destroy",function(){return p.unbind("scroll",m)})}}}]),b.module("Mac").directive("macAutocomplete",["$animate","$compile","$filter","$http","$parse","$rootScope","$timeout","keys",function(a,c,d,e,f,g,h,i){return{restrict:"EA",template:'<input type="text">',transclude:!0,replace:!0,require:"ngModel",link:function(g,j,k,l,m){var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K;return y=k.macAutocompleteLabel||"name",x=f(y),G=k.macAutocompleteQuery||"q",s=+(k.macAutocompleteDelay||800),v=null!=k.macAutocompleteInside,p=f(k.macAutocompleteUrl),B=f(k.macAutocompleteOnSelect),C=f(k.macAutocompleteOnSuccess),A=f(k.macAutocompleteOnError),I=f(k.macAutocompleteSource),t=f(k.macAutocompleteDisabled),r=[],J=null,w=!1,E=!1,n=g.$new(),n.items=[],n.index=0,n.select=function(a){var b,c;return c=r[a],B(g,{selected:c}),b=n.items[a].label||"",E=!0,null!=k.ngModel&&(l.$setViewValue(b),l.$render()),H()},z=b.element(document.createElement("mac-menu")),z.attr({"ng-class":k.macMenuClass||"","mac-menu-items":"items","mac-menu-select":"select(index)","mac-menu-index":"index"}),m(n,function(a){return z.append(a)}),c(z)(n),l.$parsers.push(function(a){return!a||t(g)||E?H():(null!=J&&h.cancel(J),s>0?J=h(function(){return F(a)},s):F(a)),E=!1,a}),q=function(){return g.$apply(function(){return H()})},o=function(){return w||(j.bind("blur",q),z.on("mousedown",function(a){return a.preventDefault()})),w=!0,z[0].style.visibility="hidden",v?a.enter(z,void 0,j):a.enter(z,b.element(document.body))},H=function(){return a.leave(z).then(function(){return n.index=0,n.items.length=0,z[0].style.top="",z[0].style.left="",w=!1,j.unbind("blur",q)})},D=function(){var a;return a=j.offset(),a.top+=j.outerHeight(),a.minWidth=j.outerWidth(),b.forEach(a,function(a,c){return!isNaN(+a)&&b.isNumber(+a)&&(a=""+a+"px"),z[0].style[c]=a}),z[0].style.visibility="visible"},K=function(a){return(null!=a?a.length:void 0)>0?(r=a,n.items=a.map(function(a){return b.isObject(a)?(null==a.value&&(a.value=x(a)||""),null==a.label&&(a.label=x(a)||""),a):{label:a,value:a}}),o().then(D)):H()},u=function(a,b){var c;return c={method:"GET",url:a,params:{}},c.params[G]=b,e(c).success(function(a,b,c){var d;return d=C(g,{data:a,status:b,headers:c}),null==d&&(d=a.data),K(d)}).error(function(a,b,c){return A(g,{data:a,status:b,headers:c})})},F=function(a){var c,e;return e=p(g),e?u(e,a):(c=I(g),b.isArray(c)?K(d("filter")(c,a)):b.isString(c)?u(c,a):b.isFunction(c)?c(a,K):void 0)},j.bind("keydown",function(a){if(0===n.items.length)return!0;switch(a.which){case i.DOWN:g.$apply(function(){return n.index=(n.index+1)%n.items.length,a.preventDefault()});break;case i.UP:g.$apply(function(){return n.index=(n.index?n.index:n.items.length)-1,a.preventDefault()});break;case i.ENTER:g.$apply(function(){return n.select(n.index),a.preventDefault()});break;case i.ESCAPE:g.$apply(function(){return H(),a.preventDefault()})}return!0}),g.$on("$destroy",function(){return n.$destroy(),H()}),g.$on("reset-mac-autocomplete",function(){return H()})}}}]),b.module("Mac").directive("macCspinner",["$timeout","util",function(c,d){return{restrict:"E",replace:"true",template:'<div class="mac-cspinner"></div>',compile:function(e,f){var g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F;if(!a.HTMLCanvasElement)return console.log("Browser does not support canvas");if(j={width:2,height:5,border:1,radius:4,bars:10,padding:3,speed:100,color:"#2f3035",size:20},q=d.extendAttributes("macCspinner",j,f),null!=f.macCspinnerSize&&(x=!isNaN(+f.macCspinnerSize)&&+f.macCspinnerSize))for(t=x/j.size,E=["width","height","border","radius"],B=0,D=E.length;D>B;B++)r=E[B],q[r]=j[r]*t;for(A=q.width,k=q.height,s=q.border,o=q.radius+k,n=Math.max(A,o),h=Math.ceil(Math.max(n,d.pyth(o,A/2))),h+=q.padding,y=b.element("<canvas></canvas>"),i=y[0].getContext("2d"),v=d.radian(360/q.bars),i.translate(h,h),z=-o,m=-A/2,u=d.hex2rgb(q.color),l=C=0,F=q.bars-1;F>=0?F>=C:C>=F;l=F>=0?++C:--C)p=1-.8/q.bars*l,i.fillStyle="rgba("+u.r+", "+u.g+", "+u.b+", "+p+")",i.beginPath(),i.moveTo(m+s,z),i.arc(m+A-s,z+s,s,d.radian(-90),d.radian(0),!1),i.arc(m+A-s,z+k-s,s,d.radian(0),d.radian(90),!1),i.arc(m+s,z+k-s,s,d.radian(90),d.radian(180),!1),i.arc(m+s,z+s,s,d.radian(-180),d.radian(-90),!1),i.closePath(),i.fill(),i.rotate(v);return g=b.element("<canvas></canvas>"),g.attr({width:2*h,height:2*h}),w=g[0].getContext("2d"),w.translate(h,h),e.append(g),function(a,b,e){var f,g,i,j;return f=null,g=!1,j=function(){return g=!1,null!=f?c.cancel(f):void 0},i=function(){var a,e;if(!g)return g=!0,e=d.radian(360/q.bars),(a=function(d){return null==d&&(d=!1),w.clearRect(-h,-h,2*h,2*h),w.rotate(e),w.drawImage(y[0],-h,-h),g?!d&&b[0].offsetHeight<=0&&b[0].offsetWidth<=0?j():f=c(a,q.speed,!1):void 0})(!0)},null!=e.macCspinnerSpin?a.$watch(e.macCspinnerSpin,function(a){return a&&!g?i():j()}):i(),e.ngShow?a.$watch(e.ngShow,function(a){return a?i():j()}):e.ngHide&&a.$watch(e.ngHide,function(a){return a?j():i()}),a.$on("$destroy",function(){return j()})}}}}]);var p,q,r,s,t;for(t=["Enter","Escape","Space","Left","Up","Right","Down"],q=function(a){return b.module("Mac").directive("macKeydown"+a,["$parse","keys",function(b,c){return{restrict:"A",link:function(d,e,f){var g;return g=b(f["macKeydown"+a]),e.bind("keydown",function(b){return b.which===c[""+a.toUpperCase()]?(b.preventDefault(),d.$apply(function(){return g(d,{$event:b})})):void 0})}}}])},r=0,s=t.length;s>r;r++)p=t[r],q(p);b.module("Mac").directive("macPauseTyping",["$parse","$timeout",function(a,b){return{restrict:"A",link:function(c,d,e){var f,g,h;return g=a(e.macPauseTyping),f=c.$eval(e.macPauseTypingDelay)||800,h=null,d.bind("keyup",function(a){return null!=h&&b.cancel(h),h=b(function(){return g(c,{$event:a})},f)})}}}]),b.module("Mac").directive("macWindowResize",["$parse","$window",function(a,c){return{restrict:"A",link:function(d,e,f){var g;return g=function(b){var c;return c=a(f.macWindowResize),d.$apply(function(){return c(d,{$event:b})}),!0},b.element(c).bind("resize",g),d.$on("destroy",function(){return b.element(c).unbind("resize",g)})}}}]),b.module("Mac").directive("macFocusOnEvent",["$timeout",function(b){return function(c,d,e){return c.$on(e.macFocusOnEvent,function(){return b(function(){var b,c;return d.focus(),e.macFocusOnEventScroll?(b=a.scrollX,c=a.scrollY,a.scrollTo(b,c)):void 0},0,!1)})}}]),b.module("Mac").factory("keys",function(){return{CANCEL:3,HELP:6,BACKSPACE:8,TAB:9,CLEAR:12,ENTER:13,RETURN:13,SHIFT:16,CONTROL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESCAPE:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,SEMICOLON:59,EQUALS:61,COMMAND:91,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,CONTEXT_MENU:93,NUMPAD0:96,NUMPAD1:97,NUMPAD2:98,NUMPAD3:99,NUMPAD4:100,NUMPAD5:101,NUMPAD6:102,NUMPAD7:103,NUMPAD8:104,NUMPAD9:105,MULTIPLY:106,ADD:107,SEPARATOR:108,SUBTRACT:109,DECIMAL:110,DIVIDE:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,F13:124,F14:125,F15:126,F16:127,F17:128,F18:129,F19:130,F20:131,F21:132,F22:133,F23:134,F24:135,NUM_LOCK:144,SCROLL_LOCK:145,COMMA:188,PERIOD:190,SLASH:191,BACK_QUOTE:192,OPEN_BRACKET:219,BACK_SLASH:220,CLOSE_BRACKET:221,QUOTE:222,META:224}}),b.module("Mac").directive("macMenu",[function(){return{restrict:"EA",replace:!0,template:'<div ng-style="style" class="mac-menu"> <ul> <li class="mac-menu-item" ng-class="{\'active\': $index == index}" ng-click="selectItem($index)" ng-mouseenter="setIndex($index)" ng-repeat="item in items" mac-menu-transclude="mac-menu-transclude"> </li> </ul></div>',transclude:!0,controller:b.noop,scope:{items:"=macMenuItems",style:"=macMenuStyle",select:"&macMenuSelect",pIndex:"=macMenuIndex"},link:function(a,b,c){return a.selectItem=function(b){return a.select({index:b})},a.setIndex=function(b){return a.index=b,null!=c.macMenuIndex?a.pIndex=parseInt(b):void 0},null!=c.macMenuIndex&&a.$watch("pIndex",function(b){return a.index=parseInt(b)}),a.$watch("items.length",function(a){return a?c.$addClass("visible"):c.$removeClass("visible")})}}}]).directive("macMenuTransclude",["$compile",function(a){return{link:function(b,c,d,e,f){return f(b,function(d){return c.empty(),0===d.length&&(d=a("<span>{{item.label}}</span>")(b)),c.append(d)})}}}]),b.module("Mac").directive("macModal",["$parse","modal","util",function(a,c,d){return{restrict:"E",template:c.modalTemplate,replace:!0,transclude:!0,link:function(e,f,g,h,i){var j,k,l,m,n,o,p,q;for(i(e,function(a){return b.element(f[0].getElementsByClassName("mac-modal-content-wrapper")).replaceWith(a)}),l=d.extendAttributes("macModal",c.defaults,g),m=null,l.overlayClose&&f.on("click",function(a){return b.element(a.target).hasClass("mac-modal-overlay")?e.$apply(function(){return c.hide()}):void 0}),q=["beforeShow","afterShow","beforeHide","afterHide","open"],o=0,p=q.length;p>o;o++)j=q[o],k="macModal"+d.capitalize(j),l[j]=a(g[k])||b.noop;return n=function(a){return null!=a&&a?(m=a,c.register(a,f,l)):void 0},g.id?n(g.id):g.$observe("macModal",function(a){return n(a)}),e.$on("$destroy",function(){return m?c.unregister(m):void 0})}}}]).directive("macModal",["$parse","modal",function(a,b){return{restrict:"A",link:function(c,d,e){e.macModal&&d.bind("click",function(){return c.$apply(function(){var d;return d=a(e.macModalData)(c)||{},b.show(e.macModal,{data:d,scope:c})})})}}}]).directive("macModalClose",["modal",function(a){return{restrict:"A",link:function(b,c){return c.bind("click",function(){return b.$apply(function(){return a.hide()})})}}}]),b.module("Mac").directive("macPlaceholder",function(){return{restrict:"A",link:function(a,b,c){return a.$watch(c.macPlaceholder,function(a){return c.$set("placeholder",a)})}}});var u=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b.module("Mac").directive("macPopover",["$timeout","popover","util",function(a,b,c){return{restrict:"A",link:function(d,e,f){var g,h,i,j,k,l,m,n;return m=c.extendAttributes("macPopover",b.defaults,f),j=f.macPopoverExclude||"",k=j?j.split(","):[],i=null,h=null,g=function(){return null!=i&&a.cancel(i),null!=h?a.cancel(h):void 0},n=function(c,f){return null==f&&(f=0),g(),i=a(function(){var a,f;return a=b.last(),null!=a&&(!k.length||(f=a.id,u.call(k,f)>=0)||a.id===c)&&(b.hide(),e[0]===a.element[0])?!0:(m.scope=d,b.show(c,e,m))},f),!0},l=function(c,d){return null==d&&(d=0),g(),h=a(function(){return b.hide(c)},d)},f.$observe("macPopover",function(a){var b,c;if(a)return"click"===m.trigger?e.bind("click",function(){return n(a,0)}):(c="focus"===m.trigger?"focusin":"mouseenter",b="focus"===m.trigger?"focusout":"mouseleave",e.bind(c,function(){return n(a,400)}),e.bind(b,function(){return l(e,500)}))})}}}]).directive("macPopover",["popover","util",function(a,c){return{restrict:"E",compile:function(d,e){var f;if(!e.id)throw Error("macPopover: Missing id");return f=c.extendAttributes("macPopover",a.popoverDefaults,e),b.extend(f,{template:d.html()}),function(b,c,d){return d.$observe("id",function(b){return a.register(b,f),c.replaceWith(document.createComment("macPopover: "+d.id))})}}}}]).directive("macPopoverFillContent",["$compile",function(a){return{restrict:"A",link:function(b,c){return c.html(b.macPopoverTemplate),a(c.contents())(b)}}}]),b.module("Mac").directive("macScrollSpy",["$window","scrollSpy","scrollSpyDefaults","util",function(a,c,d,e){return{link:function(f,g,h){var i,j;return i=e.extendAttributes("macScrollSpy",d,h),j="BODY"===g[0].tagName?b.element(a):g,j.bind("scroll",function(){var a,b,d,e,h,k,l;if(h=j.scrollTop()+i.offset,e=this.scrollHeight||g[0].scrollHeight,d=e-j.height(),!c.registered.length)return!0;if(h>=d)return c.setActive(c.last());for(b=k=0,l=c.registered.length-1;l>=0?l>=k:k>=l;b=l>=0?++k:--k)if(a=c.registered,c.active.id!==a[b].id&&h>=a[b].top&&(!a[b+1]||h<=a[b+1].top))return f.$apply(function(){return c.setActive(a[b])}),!0})}}}]).directive("macScrollSpyAnchor",["scrollSpy",function(a){return{link:function(b,c,d){var e,f,g,h;if(e=d.id||d.macScrollSpyAnchor,g=!1,!e)throw new Error("Missing scroll spy anchor id");return h=function(){return a.register(e,c),g||b.$on("$destroy",function(){return a.unregister(e)}),g=!0},b.$on("refresh-scroll-spy",h),/{{(.*)}}/.test(e)?(f=d.id?"id":"macScrollSpyAnchor",d.$observe(f,function(a){return null!=a&&a?(e=a,h()):void 0})):h()}}}]).directive("macScrollSpyTarget",["scrollSpy",function(a){return{link:function(b,c,d){var e,f,g,h;if(h=d.macScrollSpyTarget,e=d.macScrollSpyTargetClass||"active",g=!1,!h)throw new Error("Missing scroll spy target name");return f=function(d){var f;if(d)return f=function(a){var b;return b=d===a.id?"addClass":"removeClass",c[b](e)},null!=a.active&&f(a.active),g?void 0:(a.addListener(f),b.$on("$destroy",function(){return a.removeListener(f)}))},/{{(.*)}}/.test(h)?d.$observe("macScrollSpyTarget",function(a){return f(a)}):f(h)}}}]),b.module("Mac").directive("macSpinner",["util",function(a){return{restrict:"E",replace:!0,template:'<div class="mac-spinner"></div>',compile:function(c){var d,e,f,g,h,i,j,k,l,m,n,o;for(j=["webkit","Moz","ms","O"],f=[],n=function(b,c){var d,e,f;for(c=a.capitalize(c),e=0,f=j.length;f>e;e++)if(d=j[e],null!=b.style[d+c])return d+c;return c},m=function(a,c){var d,e,g,h,i,j;{if(!b.isObject(a)){for(j=[],h=0,i=f.length;i>h;h++)d=f[h],j.push(d.style[a]=c);return j}for(e in a)g=a[e],m(e,g)}},d=n(c[0],"animation"),l=n(c[0],"transform"),i=o=0;9>=o;i=++o)h=.1*i-1+!i,g=36*i,k={},e=b.element('<div class="bar"></div>'),f.push(e[0]),k[d]="fade 1s linear infinite "+h+"s",k[l]="rotate("+g+"deg) translate(0, 130%)",e.css(k),c.append(e);return function(a,c,d){var e,f;return e={size:16,zIndex:"inherit",color:"#2f3035"},f=function(a){return m({height:.32*a+"px",left:.445*a+"px",top:.37*a+"px",width:.13*a+"px",borderRadius:.32*a*2+"px",position:"absolute"}),!isNaN(+a)&&b.isNumber(+a)&&(a=""+a+"px"),c.css({height:a,width:a})},null!=d.macSpinnerSize?d.$observe("macSpinnerSize",function(a){return null!=a&&a?f(a):void 0}):f(e.size),d.$observe("macSpinnerZIndex",function(a){return null!=a&&a?c.css("z-index",a):void 0}),null!=d.macSpinnerColor?d.$observe("macSpinnerColor",function(a){return null!=a&&a?m("background",a):void 0}):m("background",e.color)}}}}]);var u=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b.module("Mac").directive("macTagAutocomplete",["$parse","$timeout","keys","util",function(a,c,d,e){return{restrict:"E",template:'<div class="mac-tag-autocomplete"> <ul class="mac-tag-list"> <li ng-repeat="tag in selected" class="mac-tag mac-label"> <div ng-click="selected.splice($index, 1)" class="mac-tag-close">&times;</div> <span class="tag-label">{{getTagLabel(tag)}}</span> </li> <li ng-class="{\'fullwidth\': !selected.length}" class="mac-tag mac-input-tag"> <mac-autocomplete class="text-input mac-autocomplete" ng-keydown="onKeyDown($event)" ng-model="textInput" mac-autocomplete-disabled="disabled" mac-autocomplete-on-select="onSelect(selected)" mac-autocomplete-on-success="onSuccess(data)" mac-placeholder="autocompletePlaceholder"></mac-autocomplete> </li> </ul></div>',replace:!0,priority:800,scope:{url:"=macTagAutocompleteUrl",placeholder:"=macTagAutocompletePlaceholder",selected:"=macTagAutocompleteSelected",source:"=macTagAutocompleteSource",disabled:"=macTagAutocompleteDisabled",model:"=macTagAutocompleteModel",onEnter:"&macTagAutocompleteOnEnter",onKeydown:"&macTagAutocompleteOnKeydown"},compile:function(f,g){var h,i,j,k,l,m,n,o,p;return p=g.macTagAutocompleteValue,null==p&&(p="id"),o=a(p),k=g.macTagAutocompleteLabel,null==k&&(k="name"),j=a(k),l=g.macTagAutocompleteQuery||"q",i=+g.macTagAutocompleteDelay||800,n=!1,m=b.element(f[0].getElementsByClassName("mac-autocomplete")),h={"mac-autocomplete-label":k,"mac-autocomplete-query":l,"mac-autocomplete-delay":i},null!=g.macTagAutocompleteUrl?h["mac-autocomplete-url"]="url":(n=null!=g.macTagAutocompleteSource)&&(h["mac-autocomplete-source"]="autocompleteSource"),m.attr(h),function(f,g,h){var i,l;return f.textInput="",f.autocompleteSource=b.isArray(f.source)?[]:f.source,null!=h.macTagAutocompleteModel&&(f.$watch("textInput",function(a){return f.model=a}),f.$watch("model",function(a){return f.textInput=a})),g.bind("click",function(){var a;return a=g[0].getElementsByClassName("mac-autocomplete"),a[0].focus()}),f.getTagLabel=function(a){return k?j(a):a},c(function(){var c,d,i,j,k,l,n,o;if(i=h.macTagAutocompleteEvents){for(m=b.element(g[0].getElementsByClassName("text-input")),n=i.split(","),o=[],k=0,l=n.length;l>k;k++)j=n[k],j=e.trim(j),c=e.capitalize(j),d=h["macTagAutocompleteOn"+c],d&&"keydown"!==j&&o.push(function(b,c){return m.bind(b,function(b){var d;return d=a(c),f.$apply(function(){return d(f.$parent,{$event:b,item:f.textInput})})})}(j,d));return o}},0,!1),i=function(){var a,c,d,e,g;return f.autocompletePlaceholder=(null!=(g=f.selected)?g.length:void 0)?"":f.placeholder,n&&b.isArray(f.source)?(e=function(){var a,b,d,e;for(d=f.source||[],e=[],a=0,b=d.length;b>a;a++)c=d[a],e.push(o(c));return e}(),d=function(){var a,b,d,e;for(d=f.selected||[],e=[],a=0,b=d.length;b>a;a++)c=d[a],e.push(o(c));return e}(),a=function(){var a,b,f;for(f=[],a=0,b=e.length;b>a;a++)c=e[a],u.call(d,c)<0&&f.push(c);return f}(),f.autocompleteSource=function(){var b,d,e,g,h;for(e=f.source||[],h=[],b=0,d=e.length;d>b;b++)c=e[b],g=o(c),u.call(a,g)>=0&&h.push(c);return h}()):void(f.autocompleteSource=f.source)},n&&(l=b.isArray(f.source)?"$watchCollection":"$watch",f[l]("source",i)),f.$watchCollection("selected",i),f.onKeyDown=function(a){var b,c;switch(b=a.which||a.keyCode){case d.BACKSPACE:f.textInput||"function"==typeof(c=f.selected).pop&&c.pop();break;case d.ENTER:f.textInput.length>0&&f.disabled&&f.onSelect(f.textInput)}return null!=h.macTagAutocompleteOnKeydown&&"function"==typeof f.onKeydown&&f.onKeydown({$event:a,value:f.textInput}),!0},f.onSuccess=function(a){var b,c;return b=function(){var a,b,d,e;for(d=f.selected||[],e=[],a=0,b=d.length;b>a;a++)c=d[a],e.push(o(c));return e}(),function(){var d,e,f,g,h;for(f=a.data,h=[],d=0,e=f.length;e>d;d++)c=f[d],g=o(c)||c,u.call(b,g)<0&&h.push(c);return h}()},f.onSelect=function(a){return null!=h.macTagAutocompleteOnEnter&&(a=f.onEnter({item:a})),a&&f.selected.push(a),c(function(){return f.textInput=""},0)},f.$on("mac-tag-autocomplete-clear-input",function(){return f.textInput=""})}}}}]),b.module("Mac").directive("macTime",["$filter","$timeout","keys","util",function(a,b,c,d){var e;return e={"default":"12:00 AM"},{restrict:"E",require:"ngModel",replace:!0,template:'<input class="mac-date-time" type="text" maxlength="8">',link:function(f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return n=d.extendAttributes("macTime",e,h),v=null,h.placeholder||h.$set("placeholder","--:--"),w=function(a){return!a||d.timeRegex.exec(a)?(i.$setValidity("time",!0),a):void i.$setValidity("time",!1)},i.$formatters.push(w),i.$parsers.push(w),(m=function(){var a;return a=(new Date).toDateString(),v=new Date(a+" "+n["default"]),isNaN(v.getTime())?v=new Date(a+" "+e["default"]):void 0})(),j=function(){var a;switch(a=g[0].selectionStart,!1){case!(a>=0&&3>a):return"hour";case!(a>=3&&6>a):return"minute";case!(a>=6&&9>a):return"meridian"}},t=function(a,c){return b(function(){return g[0].setSelectionRange(a,c)},0,!1)},o=function(){return t(0,2)},q=function(){return t(3,5)},p=function(){return t(6,8)},r=function(){switch(j()){case"hour":return q();case"minute":case"meridian":return p()}},s=function(){switch(j()){case"hour":case"minute":return o();case"meridian":return q()}},u=function(a){var b;return b=v.getHours(),b>=12&&"AM"===a&&(b-=12),12>b&&"PM"===a&&(b+=12),v.setHours(b)},x=function(){var a;return a=v.getHours(),v.setHours((a+12)%24)},k=function(a){return v.setHours(v.getHours()+a)},l=function(a){return v.setMinutes(v.getMinutes()+a)},y=function(){var b;return b=a("date")(v.getTime(),"hh:mm a"),b!==i.$viewValue?(i.$setViewValue(b),i.$render()):void 0},z=function(){var a,b,c,e;return(e=d.timeRegex.exec(i.$modelValue))?(a=+e[1],c=+e[2],b=e[3],"PM"===b&&12!==a&&(a+=12),"AM"===b&&12===a&&(a=0),v.setHours(a,c)):void 0},g.on("blur",function(){return f.$apply(function(){return y()})}),g.on("click",function(){return f.$apply(function(){switch(z(),y(),j()){case"hour":return o();case"minute":return q();case"meridian":return p()}})}),g.on("keydown",function(a){var b;return b=a.which,b!==c.UP&&b!==c.DOWN&&b!==c.LEFT&&b!==c.RIGHT&&b!==c.A&&b!==c.P?!0:(a.preventDefault(),f.$apply(function(){var a,d;switch(b){case c.UP:case c.DOWN:switch(a=b===c.UP?1:-1,j()){case"hour":k(a),o();break;case"minute":l(a),q();break;case"meridian":x(),p()}return y();case c.LEFT:case c.RIGHT:switch(b){case c.LEFT:s();break;case c.RIGHT:r()}return y();case c.A:case c.P:switch(d="meridian"===j(),!1){case!(d&&b===c.A):u("AM");break;case!(d&&b===c.P):u("PM")}return y(),p()}}))}),g.on("keyup",function(a){var b;return b=a.which,c.NUMPAD0<=b&&b<=c.NUMPAD9||c.ZERO<=b&&b<=c.NINE||a.preventDefault(),f.$apply(function(){return z()})})}}}]),b.module("Mac").directive("macTooltip",["$timeout","util",function(a,c){return{restrict:"A",link:function(d,e,f){var g,h,i,j,k,l,m,n,o,p;return p=null,n="",j=!1,i=!1,g=null,h={direction:"top",trigger:"hover",inside:!1},k=c.extendAttributes("macTooltip",h,f),m=function(){var a,c,d,f;if(i||!n||null!=p)return!0;switch(d=k.inside?e:b.element(document.body),l(0),p=b.element('<div class="mac-tooltip '+k.direction+'"><div class="tooltip-message">'+n+"</div></div>"),d.append(p),c=k.inside?{top:0,left:0}:e.offset(),a={width:e.outerWidth(),height:e.outerHeight()},f={width:p.outerWidth(),height:p.outerHeight()},k.direction){case"bottom":case"top":c.left+=a.width/2-f.width/2;break;case"left":case"right":c.top+=a.height/2-f.height/2}switch(k.direction){case"bottom":c.top+=a.height;break;case"top":c.top-=f.height;break;case"left":c.left-=f.width;break;case"right":c.left+=a.width}return c.top=Math.max(0,c.top),c.left=Math.max(0,c.left),b.forEach(c,function(a,c){return!isNaN(+a)&&b.isNumber(+a)&&(a=""+a+"px"),p.css(c,a)}),p.addClass("visible"),!0},l=function(b){return null==b&&(b=100),null!=p&&null==g&&(p.removeClass("visible"),g=a(function(){return null!=p&&p.remove(),p=null,g=null},b,!1)),!0},o=function(){return null!=p?l():m()},f.$observe("macTooltip",function(a){var b;if(null!=a&&(n=a,!j)){if("hover"!==(b=k.trigger)&&"click"!==b)throw"Invalid trigger";switch(k.trigger){case"click":e.bind("click",o);break;case"hover":e.bind("mouseenter",m),e.bind("mouseleave click",function(){return l()})}return j=!0}}),null!=f.macTooltipDisabled&&d.$watch(f.macTooltipDisabled,function(a){return i=a}),d.$on("$destroy",function(){return null!=p?l(0):void 0})}}}]),b.module("Mac").filter("boolean",function(){return function(a,b,c){return null==b&&(b="true"),null==c&&(c="false"),a?b:c}}),b.module("Mac").filter("true",function(){return function(a,b){return null==b&&(b="true"),a?b:""}}),b.module("Mac").filter("false",function(){return function(a,b){return null==b&&(b="false"),a?"":b}}),b.module("Mac").filter("list",[function(){return function(a,b){return null==b&&(b=", "),a.join(b)}}]),b.module("Mac").filter("pluralize",["util",function(a){return function(b,c,d){return null==d&&(d=!0),a.pluralize(b,c,d)}}]),b.module("Mac").filter("timestamp",["util",function(a){var b;return b=function(b,c){return c=a.pluralize(c,b),""+b+" "+c+" ago"},function(a){var c,d,e,f,g,h,i,j;return a=+a,c=Math.round(Date.now()/1e3),h=c-a,45>h?"just now":120>h?"about a minute ago":(j=Math.floor(h/31536e3),j>0?b(j,"year"):(g=Math.floor(h/2678400),g>0?b(g,"month"):(i=Math.floor(h/604800),i>0?b(i,"week"):(d=Math.floor(h/86400),d>0?b(d,"day"):(e=Math.floor(h/3600),e>0?b(e,"hour"):(f=Math.floor(h/60),f>0?b(f,"min"):""+h+" seconds ago"))))))}}]);var v=[].slice;b.module("Mac").filter("underscoreString",function(){return function(){var a,b,c;return c=arguments[0],a=arguments[1],b=3<=arguments.length?v.call(arguments,2):[],b.unshift(c),_.string[a].apply(this,b)}}),b.module("Mac").provider("modal",function(){var c,d;this.registered=d={},this.defaults=c={keyboard:!1,overlayClose:!1,resize:!0,position:!0,open:b.noop,topOffset:20,attributes:{},beforeShow:b.noop,afterShow:b.noop,beforeHide:b.noop,afterHide:b.noop},this.$get=["$animate","$compile","$controller","$document","$http","$rootScope","$templateCache","keys",function(e,f,g,h,i,j,k,l){var m,n,o;return m=function(a){var b;return a.keyCode===l.ESCAPE&&o.opened?(b=o.opened.element.scope(),b.$apply(function(){return o.hide()})):void 0},n=function(){return o.resize()},o={registered:d,defaults:c,waiting:null,opened:null,modalTemplate:'<div class="mac-modal-overlay">\n <div class="mac-modal">\n <a mac-modal-close class="mac-close-modal"></a>\n <div class="mac-modal-content-wrapper"></div>\n </div>\n</div>',show:function(a,c){var d,h,l,m,n,o,p;if(null==c&&(c={}),null!=this.registered[a]&&null!=this.opened)return this.hide();if(null==this.registered[a])return this.waiting={id:a,options:c};if(d=this.registered[a],h=d.options,o={},b.extend(o,h,c),n=function(b){return function(c){return o.beforeShow(c.scope()),e.addClass(c,"visible").then(function(){return b.opened={id:a,element:c,options:o},b.resize(b.opened),b.bindingEvents(),o.open(c.scope()),o.afterShow(c.scope()),j.$broadcast("modalWasShown",a),b.clearWaiting()})}}(this),null!=o.moduleMethod){if(m=function(c){return function(d){var h,i,k;return b.isScope(o.scope)?i=o.scope:(i=j.$new(!0),b.isObject(o.scope)&&b.extend(i,o.scope)),b.extend(o.attributes,{id:a}),h=b.element(c.modalTemplate).attr(o.attributes),k=b.element(h[0].getElementsByClassName("mac-modal-content-wrapper")),k.html(d),o.overlayClose&&h.bind("click",function(a){return b.element(a.target).hasClass("mac-modal-overlay")?i.$apply(function(){return c.hide()}):void 0}),o.controller&&g(o.controller,{$scope:i,$element:h,macModalOptions:o}),e.enter(h,b.element(document.body)),f(h)(i),n(h)}}(this),l=o.templateUrl)return p=k.get(l),p?m(p):i.get(l).then(function(a){return k.put(l,a.data),m(a.data)},function(){throw Error("Failed to load template: "+l)});if(p=o.template)return m(p)}else if(null!=d.element)return n(d.element)},resize:function(c){var d,e,f,g,h,i;return null==c&&(c=this.opened),null!=c&&(e=c.element,h=c.options,h.position)?(g=b.element(e[0].querySelector(".mac-modal")),f=g.outerHeight(),i=g.outerWidth(),d=b.element(a).height()>f?{marginTop:-f/2}:{top:h.topOffset},d.marginLeft=-i/2,b.forEach(d,function(a,c){return!isNaN(+a)&&b.isNumber(+a)&&(a=""+a+"px"),g.css(c,a)})):void 0},hide:function(){var a,c,d,f,g;if(null!=this.opened)return g=this.opened,c=g.id,d=g.options,a=g.element,d.beforeHide(a.scope()),f=this,e.removeClass(a,"visible").then(function(){var g;return f.bindingEvents("unbind"),f.opened=null,d.moduleMethod?(b.isScope(d.scope)||a.scope().$destroy(),e.leave(a)):(g=a[0].querySelector(".mac-modal"),g.removeAttribute("style")),d.afterHide(a.scope()),j.$broadcast("modalWasHidden",c)})},bindingEvents:function(c){var d;return null==c&&(c="bind"),"bind"!==c&&"unbind"!==c||null==this.opened?void 0:(d=this.opened.options,d.keyboard&&h[c]("keydown",m),d.resize?b.element(a)[c]("resize",n):void 0)},register:function(a,d,e){var f;if(null!=this.registered[a])throw new Error("Modal "+a+" already registered");return f={},b.extend(f,c,e),this.registered[a]={id:a,element:d,options:f},null!=this.waiting&&this.waiting.id===a?this.show(a,this.waiting.options):void 0},unregister:function(a){var b;if(null==this.registered[a])throw new Error("Modal "+a+" is not registered");return(null!=(b=this.opened)?b.id:void 0)===a&&this.hide(),this.clearWaiting(a),delete this.registered[a]},clearWaiting:function(a){var b;if(null==a||(null!=(b=this.waiting)?b.id:void 0)===a)return this.waiting=null}}}]}).config(["modalProvider",function(a){return b.module("Mac").modal=function(c,d){var e;
+return null==a.registered[c]?(e={},b.extend(e,a.defaults,d,{moduleMethod:!0}),a.registered[c]={id:c,options:e}):void 0}}]),b.module("Mac").provider("popover",function(){var c,d,e,f;this.registered=f={},this.defaults=c={fixed:!1,childPopover:!1,offsetY:0,offsetX:0,trigger:"click"},this.popoverDefaults=d={footer:!1,header:!1,title:"",direction:"above left"},this.template=e='<div class="mac-popover" ng-class="macPopoverClasses">\n <div class="tip"></div>\n <div class="popover-header">\n <div class="title">{{macPopoverTitle}}</div>\n </div>\n <div mac-popover-fill-content></div>\n</div>',this.$get=["$animate","$compile","$controller","$http","$rootScope","$templateCache","$timeout",function(g,h,i,j,k,l){var m;return m={popoverList:[],registered:f,defaults:c,popoverDefaults:d,template:e,last:function(){return this.popoverList[this.popoverList.length-1]},register:function(a,b){var c;return(c=null!=this.registered[a])||(this.registered[a]=b),!c},unregister:function(a){var b;return(b=null!=this.registered[a])&&delete this.registered[a],b},add:function(a,b,c,d){var e;return e={id:a,popover:b,element:c,options:d},this.popoverList.push(e),e},pop:function(){return this.popoverList.pop()},show:function(a,c,d){var f,n;return null==d&&(d={}),(n=this.registered[a])?(f=function(){var f,o,p;return o=function(f){var j,l,o;return b.isScope(d.scope)?o=d.scope.$new():(o=k.$new(!0),b.isObject(d.scope)&&b.extend(o,d.scope)),n.refreshOn&&o.$on(n.refreshOn,function(){return m.resize(a)}),n.controller&&i(n.controller,{$scope:o}),b.extend(o,{macPopoverClasses:{footer:n.footer||!1,header:n.header||!!n.title||!1,fixed:n.fixed||!1},macPopoverTitle:n.title||"",macPopoverTemplate:f}),j=h(e)(o),j.attr({id:a,direction:n.direction||"below left"}),l=m.add(a,j,c,d),g.addClass(c,"active"),k.$broadcast("popoverWasShown",a),g.enter(j,b.element(document.body)).then(function(){return m.resize(l)})},(p=n.template)?o(p):(f=n.templateUrl)?(p=l.get(f),p?o(p):j.get(f).then(function(a){return l.put(f,a.data),o(a.data)},function(){throw new Error("Failed to load template: #{path}")})):void 0},m.popoverList.length&&!d.childPopover?m.hide(f):f(),!0):!1},getById:function(a,b){var c,d,e,f,g;for(g=this.popoverList,e=0,f=g.length;f>e;e++)if(c=g[e],d=null==b||c.element===b,c.id===a&&d)return c},resize:function(c){var d,e,f,g,h,i,j,k,l,n,o,p,q,r,s,t;return b.isString(c)&&(c=m.getById(c)),null!=c?(g=c.popover,p=c.element,l=c.options,d=b.element(a),k=p.offset(),l.fixed&&(k.top=p.position().top),o={height:p.outerHeight(),width:p.outerWidth()},f={height:g.outerHeight(),width:g.outerWidth()},r=0,i=0,n=(g.attr("direction")||"top left").trim(),q=function(a){var c,d;return null==a&&(a=0),c=b.element(g[0].getElementsByClassName("tip")),r-=a,d=+c.css("margin-top").replace("px",""),c.css("margin-top",d+a)},t=function(){switch(n){case"above left":return r=-(f.height+10),i=-25+o.width/2;case"above right":return r=-(f.height+10),i=25+o.width/2-f.width;case"below left":return r=o.height+10,i=-25+o.width/2;case"below right":return r=o.height+10,i=25+o.width/2-f.width;case"middle right":return r=o.height/2-f.height/2,i=o.width+10;case"middle left":return r=o.height/2-f.height/2,i=-(f.width+10)}},t(),s=l.fixed?0:d.scrollTop(),j=l.fixed?0:d.scrollLeft(),e={},-1===n.indexOf("middle")?k.top+r-s<0?e={remove:"above",add:"below"}:k.top+r+f.height-s>d.height()&&(e={remove:"below",add:"above"}):(h=k.top+r-s)<0?q(h):(h=k.top+r+g.outerHeight()-s-d.height())>0&&q(h),e.remove&&e.add&&(n=n.replace(e.remove,e.add)),e={},k.left+i-j<0?e={remove:"right",add:"left"}:k.left+i+g.outerWidth()-j>d.width()&&(e={remove:"left",add:"right"}),e.remove&&e.add&&(n=n.replace(e.remove,e.add)),t(),k.top+=r,k.left+=i,null!=l.offsetX&&(k.left+=l.offsetX),null!=l.offsetY&&(k.top+=l.offsetY),b.forEach(k,function(a,b){return isNaN(+a)||(a=""+a+"px"),g.css(b,a)}),g.addClass("visible "+n)):void 0},hide:function(a,c){var d,e,f,h,i,j,l;if(!this.popoverList.length)return"function"==typeof c?c():void 0;if(b.isFunction(a)&&(c=a,a=null),null!=a){for(d=b.isString(a)?function(b){return b.id===a}:b.isElement(a)?function(b){return b.element===a}:void 0,f=-1,e=j=l=this.popoverList.length-1;j>=0;e=j+=-1)if(d(this.popoverList[e])){h=this.popoverList[e],f=e;break}f>-1&&this.popoverList.splice(f,1)}else h=this.pop();return null!=h?(k.$broadcast("popoverBeforeHide",h.id),g.removeClass(h.element,"active"),i=h.popover.scope(),g.leave(h.popover).then(function(){return k.$broadcast("popoverWasHidden",h.id),i.$destroy(),"function"==typeof c?c():void 0})):void 0},hideAll:function(){for(;this.popoverList.length;)this.hide()}}}]}).config(["popoverProvider",function(a){return b.module("Mac").popover=function(c,d){var e;return null==a.registered[c]?(e={},b.extend(e,a.popoverDefaults,d,{id:c}),a.registered[c]=e):void 0}}]),b.module("Mac").service("scrollSpy",[function(){return{registered:[],active:{},listeners:[],register:function(a,b){var c,d,e,f,g,h,i;for(e=!1,f=b.offset().top,i=this.registered,d=g=0,h=i.length;h>g;d=++g)if(c=i[d],c.id===a){this.registered[d]={id:a,element:b,top:f},e=!0;break}return e||this.registered.push({id:a,element:b,top:f}),this.registered.sort(function(a,b){return a.top>b.top?1:a.top<b.top?-1:0})},unregister:function(a){var b,c,d,e,f,g,h;for(f=this.registered,h=[],c=d=0,e=f.length;e>d;c=++d)if(b=f[c],b.id===a){[].splice.apply(this.registered,[c,c-c+1].concat(g=[])),g;break}return h},last:function(){return this.registered[this.registered.length-1]},setActive:function(a){var b,c,d,e,f;for(this.active=a,e=this.listeners,f=[],c=0,d=e.length;d>c;c++)b=e[c],f.push(b(a));return f},addListener:function(a){return this.listeners.push(a)},removeListener:function(a){var b,c;return b=this.listeners.indexOf(a),-1!==b?([].splice.apply(this.listeners,[b,b-b+1].concat(c=[])),c):void 0}}}]).constant("scrollSpyDefaults",{offset:0});var w={}.hasOwnProperty;b.module("Mac.Util",[]).factory("util",["$filter",function(a){return{_inflectionConstants:{uncountables:["sheep","fish","moose","series","species","money","rice","information","info","equipment","min"],irregulars:{child:"children",man:"men",woman:"women",person:"people",ox:"oxen",goose:"geese"},pluralizers:[[/(quiz)$/i,"$1zes"],[/([m|l])ouse$/i,"$1ice"],[/(matr|vert|ind)(ix|ex)$/i,"$1ices"],[/(x|ch|ss|sh)$/i,"$1es"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/(?:([^f])fe|([lr])f)$/i,"$1$2ves"],[/sis$/i,"ses"],[/([ti])um$/i,"$1a"],[/(buffal|tomat)o$/i,"$1oes"],[/(bu)s$/i,"$1ses"],[/(alias|status)$/i,"$1es"],[/(octop|vir)us$/i,"$1i"],[/(ax|test)is$/i,"$1es"],[/x$/i,"xes"],[/s$/i,"s"],[/$/,"s"]]},pluralize:function(c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q;if(null==c&&(c=""),null==e&&(e=!1),!b.isString(c)||0===this.trim(c).length)return c;if(e&&isNaN(+d))return"";if(null==d&&(d=2),q=this._inflectionConstants,l=q.pluralizers,m=q.uncountables,f=q.irregulars,n=c.split(/\s/).pop(),g=n.toUpperCase()===n,h=n.toLowerCase(),j=1===d||m.indexOf(h)>=0?n:null,null==j&&null!=f[h]&&(j=f[h]),null==j)for(o=0,p=l.length;p>o;o++)if(k=l[o],k[0].test(h)){j=n.replace(k[0],k[1]);break}return j||(j=n),g&&(j=j.toUpperCase()),i=c.slice(0,-n.length)+j,e?""+a("number")(d)+" "+i:i},trim:function(a){var b;return b=String(a)||"",null!=String.prototype.trim?b.trim():b.replace(/^\s+|\s+$/gm,"")},capitalize:function(a){var b;return b=String(a)||"",b.charAt(0).toUpperCase()+b.substring(1)},uncapitalize:function(a){var b;return b=String(a)||"",b.charAt(0).toLowerCase()+b.substring(1)},toCamelCase:function(a){return null==a&&(a=""),this.trim(a).replace(/[-_\s]+(.)?/g,function(a,b){return b.toUpperCase()})},toSnakeCase:function(a){return null==a&&(a=""),this.trim(a).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},convertKeysToCamelCase:function(a){var b,c,d;c={};for(b in a)w.call(a,b)&&(d=a[b],b=this.toCamelCase(b),"object"==typeof d&&(null!=d?d.constructor:void 0)!==Array&&(d=this.convertKeysToCamelCase(d)),c[b]=d);return c},convertKeysToSnakeCase:function(a){var b,c,d;c={};for(b in a)w.call(a,b)&&(d=a[b],b=this.toSnakeCase(b),"object"==typeof d&&(null!=d?d.constructor:void 0)!==Array&&(d=this.convertKeysToSnakeCase(d)),c[b]=d);return c},pyth:function(a,b){return Math.sqrt(a*a+b*b)},degrees:function(a){return 180*a/Math.PI},radian:function(a){return a*Math.PI/180},hex2rgb:function(a){var b,c,d;0===a.indexOf("#")&&(a=a.substring(1)),a=a.toLowerCase(),c={},3===a.length?(c.r=a.charAt(0)+a.charAt(0),c.g=a.charAt(1)+a.charAt(1),c.b=a.charAt(2)+a.charAt(2)):(c.r=a.substring(0,2),c.g=a.substring(2,4),c.b=a.substring(4));for(b in c)d=c[b],c[b]=parseInt(d,16);return c},timeRegex:/^(0?[1-9]|1[0-2]):([0-5][0-9])[\s]([AP]M)$/,_urlRegex:/(?:(http[s]?):\/\/)?(?:(www|[\d\w\-]+)\.)?([\d\w\-]+)\.([A-Za-z]{2,6})(:[\d]*)?([:\/?#\[\]@!$&'()*+,;=\w\d-._~%\\]*)?/i,_emailRegex:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,validateUrl:function(a){var b;return b=this._urlRegex.exec(a),null!=b&&(b={url:b[0],protocol:b[1]||"http",subdomain:b[2],name:b[3],domain:b[4],port:b[5],path:b[6]||"/"},b.url=b.url),b},validateEmail:function(a){return this._emailRegex.test(a)},getQueryString:function(a,b){var c,d,e;return null==b&&(b=""),b=b.replace(/[[]/,"[").replace(/[]]/,"]"),d="[?&]"+b+"=([^&#]*)",c=new RegExp(d),e=c.exec(a),null!=e?e[1]:""},parseUrlPath:function(a){var b,c,d,e,f,g,h,i,j,k,l;if(g=a.split("?"),c=g[0].split("/"),b=c.slice(0,c.length-1).join("/"),i=c[c.length-1],d={},g.length>1)for(f=g[g.length-1],l=f.split("&"),j=0,k=l.length;k>j;j++)e=l[j],h=e.split("="),d[h[0]]=null!=h[1]?h[1]:"";return{fullPath:a,path:b,pathComponents:c,verb:i,queries:d}},extendAttributes:function(a,b,c){var d,e,f,g,h,i,j;null==a&&(a=""),g={};for(e in b)w.call(b,e)&&(h=b[e],d=a?this.capitalize(e):e,f=""+a+d,g[e]=null!=c[f]?c[f]||!0:h,"true"===(i=g[e])||"false"===i?g[e]="true"===g[e]:(null!=(j=g[e])?j.length:void 0)>0&&!isNaN(+g[e])&&(g[e]=+g[e]));return g}}}])}(window,window.angular); \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.css b/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.css
index ba0d1e2c..35b247dc 100644
--- a/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.css
+++ b/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.css
@@ -24,15 +24,15 @@
width: 1px;
}
.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
- background-color: #d4d4d4;
+ background-color: #ccdbe6;
}
.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
- background-color: #d4d4d4;
+ background-color: #ccdbe6;
}
.ui-grid-header-cell:last-child .ui-grid-vertical-bar {
right: -1px;
width: 1px;
- background-color: #d4d4d4;
+ background-color: #ccdbe6;
}
.ui-grid-clearfix:before,
.ui-grid-clearfix:after {
@@ -54,7 +54,7 @@
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
}
.ui-grid-header {
- border-bottom: 1px solid #d4d4d4;
+ border-bottom: 1px solid #ccdbe6;
box-sizing: content-box;
}
.ui-grid-top-panel {
@@ -106,7 +106,7 @@
bottom: 0;
background-color: white;
border-right: 1px solid;
- border-color: #d4d4d4;
+ border-color: #ccdbe6;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
@@ -210,7 +210,7 @@ input[type="text"].ui-grid-filter-input {
margin: 0;
border: 0;
width: 100%;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
-webkit-border-top-right-radius: 0px;
-webkit-border-bottom-right-radius: 0;
-webkit-border-bottom-left-radius: 0;
@@ -228,7 +228,7 @@ input[type="text"].ui-grid-filter-input {
background-clip: padding-box;
}
input[type="text"].ui-grid-filter-input:hover {
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
}
.ui-grid-render-container {
position: inherit;
@@ -269,7 +269,7 @@ input[type="text"].ui-grid-filter-input:hover {
background-color: #fff;
}
.ui-grid-row:last-child .ui-grid-cell {
- border-bottom-color: #d4d4d4;
+ border-bottom-color: #ccdbe6;
border-bottom-style: solid;
}
.ui-grid-no-row-overlay {
@@ -300,7 +300,7 @@ input[type="text"].ui-grid-filter-input:hover {
-moz-background-clip: padding-box;
-webkit-background-clip: padding-box;
background-clip: padding-box;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
font-size: 2em;
text-align: center;
}
@@ -320,7 +320,8 @@ input[type="text"].ui-grid-filter-input:hover {
float: left;
background-color: inherit;
border-right: 1px solid;
- border-color: #d4d4d4;
+ border-bottom: 1px solid;
+ border-color: #ccdbe6;
box-sizing: border-box;
}
.ui-grid-cell-contents {
@@ -343,7 +344,7 @@ input[type="text"].ui-grid-filter-input:hover {
}
.ui-grid-row-header-cell {
background-color: #F0F0EE !important;
- border-bottom: solid 1px #d4d4d4;
+ border-bottom: solid 1px #ccdbe6;
}
.ui-grid-native-scrollbar {
position: absolute;
@@ -373,8 +374,8 @@ input[type="text"].ui-grid-filter-input:hover {
}
.ui-grid-footer-panel {
position: relative;
- border-bottom: 1px solid #d4d4d4;
- border-top: 1px solid #d4d4d4;
+ border-bottom: 1px solid #ccdbe6;
+ border-top: 1px solid #ccdbe6;
overflow: hidden;
font-weight: bold;
background: #f3f3f3;
@@ -423,7 +424,7 @@ input[type="text"].ui-grid-filter-input:hover {
float: left;
background-color: inherit;
border-right: 1px solid;
- border-color: #d4d4d4;
+ border-color: #ccdbe6;
box-sizing: border-box;
}
.ui-grid-footer-cell:last-child {
@@ -434,7 +435,7 @@ input[type="text"].ui-grid-filter-input {
margin: 0;
border: 0;
width: 100%;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
-webkit-border-top-right-radius: 0px;
-webkit-border-bottom-right-radius: 0;
-webkit-border-bottom-left-radius: 0;
@@ -452,14 +453,14 @@ input[type="text"].ui-grid-filter-input {
background-clip: padding-box;
}
input[type="text"].ui-grid-filter-input:hover {
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
}
.ui-grid-menu-button {
z-index: 2;
position: absolute;
right: 0;
background: #f3f3f3;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
cursor: pointer;
min-height: 27px;
font-weight: normal;
@@ -473,7 +474,7 @@ input[type="text"].ui-grid-filter-input:hover {
.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {
overflow-y: scroll;
max-height: 300px;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
}
.ui-grid-menu {
z-index: 2;
@@ -485,7 +486,7 @@ input[type="text"].ui-grid-filter-input:hover {
}
.ui-grid-menu .ui-grid-menu-inner {
background: #f3f3f3;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
position: relative;
white-space: nowrap;
-webkit-border-radius: 0px;
@@ -516,7 +517,7 @@ input[type="text"].ui-grid-filter-input:hover {
background-color: #cecece;
}
.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) {
- border-bottom: 1px solid #d4d4d4;
+ border-bottom: 1px solid #ccdbe6;
}
.ui-grid-sortarrow {
right: 5px;
@@ -609,7 +610,7 @@ input[type="text"].ui-grid-filter-input:hover {
.ui-grid[dir=rtl] .ui-grid-cell:last-child,
.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {
border-left: 1px solid;
- border-color: #d4d4d4;
+ border-color: #ccdbe6;
}
.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,
.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,
@@ -622,7 +623,7 @@ input[type="text"].ui-grid-filter-input:hover {
left: 0;
right: auto;
background: #f3f3f3;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
cursor: pointer;
min-height: 27px;
font-weight: normal;
@@ -821,7 +822,7 @@ div.ui-grid-cell input.ng-invalid {
border: 1px solid #fc8f8f;
}
div.ui-grid-cell input.ng-valid {
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
}
/* This file contains variable declarations (do not remove this line) */
@@ -927,7 +928,7 @@ div.ui-grid-cell input.ng-valid {
/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
.movingColumn {
position: fixed;
- border: 1px solid #d4d4d4;
+ border: 1px solid #ccdbe6;
box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
}
.movingColumn .ui-grid-icon-angle-down {
@@ -1060,7 +1061,7 @@ div.ui-grid-cell input.ng-valid {
width: 1px;
}
.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
- background-color: #d4d4d4;
+ background-color: #ccdbe6;
}
.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
background-color: #aeaeae;
@@ -1087,7 +1088,7 @@ div.ui-grid-cell input.ng-valid {
width: 1px;
}
.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {
- background-color: #d4d4d4;
+ background-color: #ccdbe6;
}
.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
background-color: #aeaeae;
diff --git a/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.min.css b/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.min.css
index 41231c3e..6f34f941 100644
--- a/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.min.css
+++ b/openk-platform/openk-theme/src/main/webapp/js/ng-grid/ui-grid.min.css
@@ -1,4 +1,4 @@
/*!
* ui-grid - v3.0.0-RC.18-7774d30 - 2015-02-03
* Copyright (c) 2015 ; License: MIT
- */.ui-grid{border:1px solid #ccdbe6;box-sizing:content-box;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-o-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}.ui-grid-vertical-bar{position:absolute;right:0;width:0}.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{width:1px;background-color:#d4d4d4}.ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#d4d4d4}.ui-grid-clearfix:after,.ui-grid-clearfix:before{content:"";display:table}.ui-grid-clearfix:after{clear:both}.ui-grid-invisible{visibility:hidden}.ui-grid-top-panel-background{background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-header{border-bottom:1px solid #d4d4d4;box-sizing:content-box}.ui-grid-top-panel{position:relative;overflow:hidden;font-weight:700;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:-1px -1px 0 0;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-radius:-1px -1px 0 0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-header-viewport{overflow:hidden}.ui-grid-header-canvas{position:relative}.ui-grid-header-canvas:after,.ui-grid-header-canvas:before{content:"";display:table;line-height:0}.ui-grid-header-canvas:after{clear:both}.ui-grid-header-cell{position:relative;box-sizing:border-box;float:left;top:0;bottom:0;background-color:#fff;border-right:1px solid;border-color:#d4d4d4;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:0}.ui-grid-header-cell .sortable{cursor:pointer}.ui-grid-header .ui-grid-vertical-bar{top:0;bottom:0}.ui-grid-column-menu-button{position:absolute;right:1px;top:0}.ui-grid-column-menu-button .ui-grid-icon-angle-down{vertical-align:sub}.ui-grid-column-menu-button-last-col{margin-right:25px}.ui-grid-column-menu{position:absolute}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block!important}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block!important}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-filter-container{padding:4px 10px;position:relative}.ui-grid-filter-container .ui-grid-filter-button{position:absolute;top:0;bottom:0;right:0}.ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]{position:absolute;top:50%;line-height:32px;margin-top:-16px;right:10px;opacity:.66}.ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]:hover{opacity:1}.ui-grid-render-container{position:inherit;-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-render-container:focus{outline:0}.ui-grid-viewport{min-height:20px;position:relative}.ui-grid-viewport :focus{outline:0}.ui-grid-canvas{position:relative;padding-top:1px}.ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#f5f8fc}.ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#fff}.ui-grid-row:last-child .ui-grid-cell{border-bottom-color:#d4d4d4;border-bottom-style:solid}.ui-grid-no-row-overlay{position:absolute;top:0;bottom:0;left:0;right:0;margin:10%;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #d4d4d4;font-size:2em;text-align:center}.ui-grid-no-row-overlay>*{position:absolute;display:table;margin:auto 0;width:100%;top:0;bottom:0;left:0;right:0;opacity:.66}.ui-grid-cell{overflow:hidden;float:left;background-color:inherit;border-right:1px solid;border-color:#d4d4d4;box-sizing:border-box}.ui-grid-cell-contents{padding:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;height:100%}.ui-grid-cell-contents-hidden{visibility:hidden;width:0;height:0;display:none}.ui-grid-row-header-cell{background-color:#F0F0EE!important;border-bottom:solid 1px #d4d4d4}.ui-grid-native-scrollbar{position:absolute;overflow:scroll}.ui-grid-native-scrollbar.vertical{top:0;right:0;height:100%;overflow-x:hidden;width:17px}.ui-grid-native-scrollbar.horizontal{bottom:0;left:0;width:100%;overflow-y:hidden;height:17px}.ui-grid-footer-panel-background{background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-footer-panel{position:relative;border-bottom:1px solid #d4d4d4;border-top:1px solid #d4d4d4;overflow:hidden;font-weight:700;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:-1px -1px 0 0;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-radius:-1px -1px 0 0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-grid-footer{float:left;width:100%}.ui-grid-footer-viewport{overflow:hidden}.ui-grid-footer-canvas{position:relative}.ui-grid-footer-canvas:after,.ui-grid-footer-canvas:before{content:"";display:table;line-height:0}.ui-grid-footer-canvas:after{clear:both}.ui-grid-footer-cell{overflow:hidden;float:left;background-color:inherit;border-right:1px solid;border-color:#d4d4d4;box-sizing:border-box}.ui-grid-footer-cell:last-child{border-right:0}input[type=text].ui-grid-filter-input{padding:0;margin:0;width:100%;border:1px solid #d4d4d4;-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}input[type=text].ui-grid-filter-input:hover{border:1px solid #d4d4d4}.ui-grid-menu-button{z-index:2;position:absolute;right:0;background:#f3f3f3;border:1px solid #d4d4d4;cursor:pointer;min-height:27px;font-weight:400}.ui-grid-menu-button .ui-grid-icon-container{margin-top:3px}.ui-grid-menu-button .ui-grid-menu{right:0}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid{overflow-y:scroll;max-height:300px;border:1px solid #d4d4d4}.ui-grid-menu{z-index:2;position:absolute;overflow:hidden;padding:0 10px 20px;cursor:pointer;box-sizing:content-box}.ui-grid-menu .ui-grid-menu-inner{background:#f3f3f3;border:1px solid #d4d4d4;position:relative;white-space:nowrap;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2);-moz-box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2);box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2)}.ui-grid-menu .ui-grid-menu-inner ul{margin:0;padding:0;list-style-type:none}.ui-grid-menu .ui-grid-menu-inner ul li{padding:8px;cursor:pointer}.ui-grid-menu .ui-grid-menu-inner ul li:hover{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,.2);box-shadow:inset 0 0 14px rgba(0,0,0,.2)}.ui-grid-menu .ui-grid-menu-inner ul li.ui-grid-menu-item-active{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,.2);box-shadow:inset 0 0 14px rgba(0,0,0,.2);background-color:#cecece}.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child){border-bottom:1px solid #d4d4d4}.ui-grid-sortarrow{right:5px;position:absolute;width:20px;top:0;bottom:0;background-position:center}.ui-grid-sortarrow.down{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}@font-face{font-family:ui-grid;src:url(ui-grid.eot);src:url(ui-grid.eot#iefix) format('embedded-opentype'),url(ui-grid.woff) format('woff'),url(ui-grid.ttf?) format('truetype'),url(ui-grid.svg?#ui-grid) format('svg');font-weight:400;font-style:normal}[class*=" ui-grid-icon"]:before,[class^=ui-grid-icon]:before{font-family:ui-grid;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em}.ui-grid-icon-blank::before{width:1em;content:' '}.ui-grid[dir=rtl] .ui-grid-cell,.ui-grid[dir=rtl] .ui-grid-footer-cell,.ui-grid[dir=rtl] .ui-grid-header-cell{float:right!important}.ui-grid[dir=rtl] .ui-grid-scrollbar-horizontal{left:inherit;right:0}.ui-grid[dir=rtl] .ui-grid-native-scrollbar.vertical{left:0;right:inherit}.ui-grid[dir=rtl] .ui-grid-column-menu-button{position:absolute;left:1px;top:0;right:inherit}.ui-grid[dir=rtl] .ui-grid-cell:first-child,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child,.ui-grid[dir=rtl] .ui-grid-header-cell:first-child{border-right:0}.ui-grid[dir=rtl] .ui-grid-cell:last-child,.ui-grid[dir=rtl] .ui-grid-header-cell:last-child{border-left:1px solid;border-color:#d4d4d4}.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar{width:0}.ui-grid[dir=rtl] .ui-grid-menu-button{z-index:2;position:absolute;left:0;right:auto;background:#f3f3f3;border:1px solid #d4d4d4;cursor:pointer;min-height:27px;font-weight:400}.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu{left:0;right:auto}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button{right:initial;left:0}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]{right:initial;left:10px}.ui-grid-animate-spin{-moz-animation:ui-grid-spin 2s infinite linear;-o-animation:ui-grid-spin 2s infinite linear;-webkit-animation:ui-grid-spin 2s infinite linear;animation:ui-grid-spin 2s infinite linear;display:inline-block}@-moz-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-ms-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.ui-grid-cell-focus{outline:0;background-color:#b3c4c7}div.ui-grid-cell input{border-radius:inherit;padding:0;width:100%;color:inherit;height:auto;font:inherit;outline:0}div.ui-grid-cell input:focus{color:inherit;outline:0}div.ui-grid-cell input[type=checkbox]{margin:9px 0 0 6px;width:auto}div.ui-grid-cell input.ng-invalid{border:1px solid #fc8f8f}div.ui-grid-cell input.ng-valid{border:1px solid #d4d4d4}.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#fdfdfd}.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#f3f3f3}.movingColumn{position:fixed;border:1px solid #d4d4d4;box-shadow:inset 0 0 14px rgba(0,0,0,.2)}.movingColumn .ui-grid-icon-angle-down{display:none}.ui-grid-pager-panel{position:absolute;left:0;bottom:0;width:100%;padding-top:3px;padding-bottom:3px}.ui-grid-pager-container{float:left}.ui-grid-pager-control{margin-right:10px;margin-left:10px;min-width:135px;float:left}.ui-grid-pager-control button{height:25px;min-width:26px}.ui-grid-pager-control input{height:26px;width:50px;vertical-align:top}.ui-grid-pager-control .first-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:-3px}.ui-grid-pager-control .first-triangle{width:0;height:0;border-style:solid;border-width:5px 8.7px 5px 0;border-color:transparent #4d4d4d transparent transparent;margin-left:2px}.ui-grid-pager-control .next-triangle{margin-left:1px}.ui-grid-pager-control .prev-triangle{margin-left:0}.ui-grid-pager-control .last-triangle{width:0;height:0;border-style:solid;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #4d4d4d;margin-left:-1px}.ui-grid-pager-control .last-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:1px}.ui-grid-pager-row-count-picker{float:left}.ui-grid-pager-row-count-picker select{height:26px;width:60px}.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label{margin-top:3px}.ui-grid-pager-count-container{float:right;margin-top:4px;min-width:50px}.ui-grid-pager-count-container .ui-grid-pager-count{margin-right:10px;margin-left:10px;float:right}.ui-grid-pinned-container{float:left}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child,.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child{box-sizing:border-box;border-right:1px solid;border-width:1px;border-color:#aeaeae}.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child,.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child{box-sizing:border-box;border-left:1px solid;border-width:1px;border-color:#aeaeae}.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar,.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar{left:-1px;width:1px;background-color:#aeaeae}.ui-grid-render-container-body{float:left}.ui-grid-column-resizer{top:0;bottom:0;width:5px;position:absolute;cursor:col-resize}.ui-grid-column-resizer.left{left:0}.ui-grid-column-resizer.right{right:0}.ui-grid.column-resizing{cursor:col-resize}.ui-grid.column-resizing .ui-grid-resize-overlay{position:absolute;top:0;height:100%;width:1px;background-color:#aeaeae}.ui-grid-row-saving .ui-grid-cell{color:#848484!important}.ui-grid-row-dirty .ui-grid-cell{color:#610b38}.ui-grid-row-error .ui-grid-cell{color:red!important}.ui-grid-row-selected>[ui-grid-row]>.ui-grid-cell{background-color:#c9dde1!important}.ui-grid-disable-selection{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.ui-grid-selection-row-header-buttons{cursor:pointer;opacity:.1}.ui-grid-selection-row-header-buttons.ui-grid-all-selected,.ui-grid-selection-row-header-buttons.ui-grid-row-selected{opacity:1}.ui-grid-icon-plus-squared:before{content:'\c350'}.ui-grid-icon-minus-squared:before{content:'\c351'}.ui-grid-icon-search:before{content:'\c352'}.ui-grid-icon-cancel:before{content:'\c353'}.ui-grid-icon-info-circled:before{content:'\c354'}.ui-grid-icon-lock:before{content:'\c355'}.ui-grid-icon-lock-open:before{content:'\c356'}.ui-grid-icon-pencil:before{content:'\c357'}.ui-grid-icon-down-dir:before{content:'\c358'}.ui-grid-icon-up-dir:before{content:'\c359'}.ui-grid-icon-left-dir:before{content:'\c35a'}.ui-grid-icon-right-dir:before{content:'\c35b'}.ui-grid-icon-left-open:before{content:'\c35c'}.ui-grid-icon-right-open:before{content:'\c35d'}.ui-grid-icon-angle-down:before{content:'\c35e'}.ui-grid-icon-filter:before{content:'\c35f'}.ui-grid-icon-sort-alt-up:before{content:'\c360'}.ui-grid-icon-sort-alt-down:before{content:'\c361'}.ui-grid-icon-ok:before{content:'\c362'}.ui-grid-icon-menu:before{content:'\c363'}.ui-grid-icon-spin5:before{content:'\ea61'} \ No newline at end of file
+ */.ui-grid{border:1px solid #ccdbe6;box-sizing:content-box;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-o-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}.ui-grid-vertical-bar{position:absolute;right:0;width:0}.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{width:1px;background-color:#ccdbe6}.ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#ccdbe6}.ui-grid-clearfix:after,.ui-grid-clearfix:before{content:"";display:table}.ui-grid-clearfix:after{clear:both}.ui-grid-invisible{visibility:hidden}.ui-grid-top-panel-background{background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-header{border-bottom:1px solid #ccdbe6;box-sizing:content-box}.ui-grid-top-panel{position:relative;overflow:hidden;font-weight:700;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:-1px -1px 0 0;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-radius:-1px -1px 0 0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-header-viewport{overflow:hidden}.ui-grid-header-canvas{position:relative}.ui-grid-header-canvas:after,.ui-grid-header-canvas:before{content:"";display:table;line-height:0}.ui-grid-header-canvas:after{clear:both}.ui-grid-header-cell{position:relative;box-sizing:border-box;float:left;top:0;bottom:0;background-color:#fff;border-right:1px solid;border-color:#ccdbe6;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:0}.ui-grid-header-cell .sortable{cursor:pointer}.ui-grid-header .ui-grid-vertical-bar{top:0;bottom:0}.ui-grid-column-menu-button{position:absolute;right:1px;top:0}.ui-grid-column-menu-button .ui-grid-icon-angle-down{vertical-align:sub}.ui-grid-column-menu-button-last-col{margin-right:25px}.ui-grid-column-menu{position:absolute}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block!important}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block!important}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-filter-container{padding:4px 10px;position:relative}.ui-grid-filter-container .ui-grid-filter-button{position:absolute;top:0;bottom:0;right:0}.ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]{position:absolute;top:50%;line-height:32px;margin-top:-16px;right:10px;opacity:.66}.ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]:hover{opacity:1}.ui-grid-render-container{position:inherit;-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-render-container:focus{outline:0}.ui-grid-viewport{min-height:20px;position:relative}.ui-grid-viewport :focus{outline:0}.ui-grid-canvas{position:relative;padding-top:1px}.ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#f5f8fc}.ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#fff}.ui-grid-row:last-child .ui-grid-cell{border-bottom-color:#ccdbe6;border-bottom-style:solid}.ui-grid-no-row-overlay{position:absolute;top:0;bottom:0;left:0;right:0;margin:10%;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccdbe6;font-size:2em;text-align:center}.ui-grid-no-row-overlay>*{position:absolute;display:table;margin:auto 0;width:100%;top:0;bottom:0;left:0;right:0;opacity:.66}.ui-grid-cell{overflow:hidden;float:left;background-color:inherit;border-right:1px solid;border-bottom:1px solid;border-color:#ccdbe6;box-sizing:border-box}.ui-grid-cell-contents{padding:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;height:100%}.ui-grid-cell-contents-hidden{visibility:hidden;width:0;height:0;display:none}.ui-grid-row-header-cell{background-color:#F0F0EE!important;border-bottom:solid 1px #ccdbe6}.ui-grid-native-scrollbar{position:absolute;overflow:scroll}.ui-grid-native-scrollbar.vertical{top:0;right:0;height:100%;overflow-x:hidden;width:17px}.ui-grid-native-scrollbar.horizontal{bottom:0;left:0;width:100%;overflow-y:hidden;height:17px}.ui-grid-footer-panel-background{background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-footer-panel{position:relative;border-bottom:1px solid #ccdbe6;border-top:1px solid #ccdbe6;overflow:hidden;font-weight:700;background:#f3f3f3;background:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(1,#fff));background:-ms-linear-gradient(bottom,#eee,#fff);background:-moz-linear-gradient(center bottom,#eee 0,#fff 100%);background:-o-linear-gradient(#fff,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-radius:-1px -1px 0 0;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-radius:-1px -1px 0 0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-grid-footer{float:left;width:100%}.ui-grid-footer-viewport{overflow:hidden}.ui-grid-footer-canvas{position:relative}.ui-grid-footer-canvas:after,.ui-grid-footer-canvas:before{content:"";display:table;line-height:0}.ui-grid-footer-canvas:after{clear:both}.ui-grid-footer-cell{overflow:hidden;float:left;background-color:inherit;border-right:1px solid;border-color:#ccdbe6;box-sizing:border-box}.ui-grid-footer-cell:last-child{border-right:0}input[type=text].ui-grid-filter-input{padding:0;margin:0;width:100%;border:1px solid #ccdbe6;-webkit-border-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}input[type=text].ui-grid-filter-input:hover{border:1px solid #ccdbe6}.ui-grid-menu-button{z-index:2;position:absolute;right:0;background:#f3f3f3;border:1px solid #ccdbe6;cursor:pointer;min-height:27px;font-weight:400}.ui-grid-menu-button .ui-grid-icon-container{margin-top:3px}.ui-grid-menu-button .ui-grid-menu{right:0}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid{overflow-y:scroll;max-height:300px;border:1px solid #ccdbe6}.ui-grid-menu{z-index:2;position:absolute;overflow:hidden;padding:0 10px 20px;cursor:pointer;box-sizing:content-box}.ui-grid-menu .ui-grid-menu-inner{background:#f3f3f3;border:1px solid #ccdbe6;position:relative;white-space:nowrap;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2);-moz-box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2);box-shadow:0 10px 20px rgba(0,0,0,.2),inset 0 12px 12px -14px rgba(0,0,0,.2)}.ui-grid-menu .ui-grid-menu-inner ul{margin:0;padding:0;list-style-type:none}.ui-grid-menu .ui-grid-menu-inner ul li{padding:8px;cursor:pointer}.ui-grid-menu .ui-grid-menu-inner ul li:hover{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,.2);box-shadow:inset 0 0 14px rgba(0,0,0,.2)}.ui-grid-menu .ui-grid-menu-inner ul li.ui-grid-menu-item-active{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,.2);box-shadow:inset 0 0 14px rgba(0,0,0,.2);background-color:#cecece}.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child){border-bottom:1px solid #ccdbe6}.ui-grid-sortarrow{right:5px;position:absolute;width:20px;top:0;bottom:0;background-position:center}.ui-grid-sortarrow.down{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}@font-face{font-family:ui-grid;src:url(ui-grid.eot);src:url(ui-grid.eot#iefix) format('embedded-opentype'),url(ui-grid.woff) format('woff'),url(ui-grid.ttf?) format('truetype'),url(ui-grid.svg?#ui-grid) format('svg');font-weight:400;font-style:normal}[class*=" ui-grid-icon"]:before,[class^=ui-grid-icon]:before{font-family:ui-grid;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em}.ui-grid-icon-blank::before{width:1em;content:' '}.ui-grid[dir=rtl] .ui-grid-cell,.ui-grid[dir=rtl] .ui-grid-footer-cell,.ui-grid[dir=rtl] .ui-grid-header-cell{float:right!important}.ui-grid[dir=rtl] .ui-grid-scrollbar-horizontal{left:inherit;right:0}.ui-grid[dir=rtl] .ui-grid-native-scrollbar.vertical{left:0;right:inherit}.ui-grid[dir=rtl] .ui-grid-column-menu-button{position:absolute;left:1px;top:0;right:inherit}.ui-grid[dir=rtl] .ui-grid-cell:first-child,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child,.ui-grid[dir=rtl] .ui-grid-header-cell:first-child{border-right:0}.ui-grid[dir=rtl] .ui-grid-cell:last-child,.ui-grid[dir=rtl] .ui-grid-header-cell:last-child{border-left:1px solid;border-color:#ccdbe6}.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar{width:0}.ui-grid[dir=rtl] .ui-grid-menu-button{z-index:2;position:absolute;left:0;right:auto;background:#f3f3f3;border:1px solid #ccdbe6;cursor:pointer;min-height:27px;font-weight:400}.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu{left:0;right:auto}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button{right:initial;left:0}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=ui-grid-icon]{right:initial;left:10px}.ui-grid-animate-spin{-moz-animation:ui-grid-spin 2s infinite linear;-o-animation:ui-grid-spin 2s infinite linear;-webkit-animation:ui-grid-spin 2s infinite linear;animation:ui-grid-spin 2s infinite linear;display:inline-block}@-moz-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-ms-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.ui-grid-cell-focus{outline:0;background-color:#b3c4c7}div.ui-grid-cell input{border-radius:inherit;padding:0;width:100%;color:inherit;height:auto;font:inherit;outline:0}div.ui-grid-cell input:focus{color:inherit;outline:0}div.ui-grid-cell input[type=checkbox]{margin:9px 0 0 6px;width:auto}div.ui-grid-cell input.ng-invalid{border:1px solid #fc8f8f}div.ui-grid-cell input.ng-valid{border:1px solid #ccdbe6}.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#fdfdfd}.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#f3f3f3}.movingColumn{position:fixed;border:1px solid #ccdbe6;box-shadow:inset 0 0 14px rgba(0,0,0,.2)}.movingColumn .ui-grid-icon-angle-down{display:none}.ui-grid-pager-panel{position:absolute;left:0;bottom:0;width:100%;padding-top:3px;padding-bottom:3px}.ui-grid-pager-container{float:left}.ui-grid-pager-control{margin-right:10px;margin-left:10px;min-width:135px;float:left}.ui-grid-pager-control button{height:25px;min-width:26px}.ui-grid-pager-control input{height:26px;width:50px;vertical-align:top}.ui-grid-pager-control .first-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:-3px}.ui-grid-pager-control .first-triangle{width:0;height:0;border-style:solid;border-width:5px 8.7px 5px 0;border-color:transparent #4d4d4d transparent transparent;margin-left:2px}.ui-grid-pager-control .next-triangle{margin-left:1px}.ui-grid-pager-control .prev-triangle{margin-left:0}.ui-grid-pager-control .last-triangle{width:0;height:0;border-style:solid;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #4d4d4d;margin-left:-1px}.ui-grid-pager-control .last-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:1px}.ui-grid-pager-row-count-picker{float:left}.ui-grid-pager-row-count-picker select{height:26px;width:60px}.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label{margin-top:3px}.ui-grid-pager-count-container{float:right;margin-top:4px;min-width:50px}.ui-grid-pager-count-container .ui-grid-pager-count{margin-right:10px;margin-left:10px;float:right}.ui-grid-pinned-container{float:left}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child,.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child{box-sizing:border-box;border-right:1px solid;border-width:1px;border-color:#aeaeae}.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#ccdbe6}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child,.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child{box-sizing:border-box;border-left:1px solid;border-width:1px;border-color:#aeaeae}.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar,.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar{background-color:#ccdbe6}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar{left:-1px;width:1px;background-color:#aeaeae}.ui-grid-render-container-body{float:left}.ui-grid-column-resizer{top:0;bottom:0;width:5px;position:absolute;cursor:col-resize}.ui-grid-column-resizer.left{left:0}.ui-grid-column-resizer.right{right:0}.ui-grid.column-resizing{cursor:col-resize}.ui-grid.column-resizing .ui-grid-resize-overlay{position:absolute;top:0;height:100%;width:1px;background-color:#aeaeae}.ui-grid-row-saving .ui-grid-cell{color:#848484!important}.ui-grid-row-dirty .ui-grid-cell{color:#610b38}.ui-grid-row-error .ui-grid-cell{color:red!important}.ui-grid-row-selected>[ui-grid-row]>.ui-grid-cell{background-color:#c9dde1!important}.ui-grid-disable-selection{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.ui-grid-selection-row-header-buttons{cursor:pointer;opacity:.1}.ui-grid-selection-row-header-buttons.ui-grid-all-selected,.ui-grid-selection-row-header-buttons.ui-grid-row-selected{opacity:1}.ui-grid-icon-plus-squared:before{content:'\c350'}.ui-grid-icon-minus-squared:before{content:'\c351'}.ui-grid-icon-search:before{content:'\c352'}.ui-grid-icon-cancel:before{content:'\c353'}.ui-grid-icon-info-circled:before{content:'\c354'}.ui-grid-icon-lock:before{content:'\c355'}.ui-grid-icon-lock-open:before{content:'\c356'}.ui-grid-icon-pencil:before{content:'\c357'}.ui-grid-icon-down-dir:before{content:'\c358'}.ui-grid-icon-up-dir:before{content:'\c359'}.ui-grid-icon-left-dir:before{content:'\c35a'}.ui-grid-icon-right-dir:before{content:'\c35b'}.ui-grid-icon-left-open:before{content:'\c35c'}.ui-grid-icon-right-open:before{content:'\c35d'}.ui-grid-icon-angle-down:before{content:'\c35e'}.ui-grid-icon-filter:before{content:'\c35f'}.ui-grid-icon-sort-alt-up:before{content:'\c360'}.ui-grid-icon-sort-alt-down:before{content:'\c361'}.ui-grid-icon-ok:before{content:'\c362'}.ui-grid-icon-menu:before{content:'\c363'}.ui-grid-icon-spin5:before{content:'\ea61'} \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore-min.js b/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore-min.js
new file mode 100644
index 00000000..f01025b7
--- /dev/null
+++ b/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore-min.js
@@ -0,0 +1,6 @@
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
+//# sourceMappingURL=underscore-min.map \ No newline at end of file
diff --git a/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore.js b/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore.js
new file mode 100644
index 00000000..f54cffa4
--- /dev/null
+++ b/openk-platform/openk-theme/src/main/webapp/js/underscore-1.8.3/underscore.js
@@ -0,0 +1,1564 @@
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
+ // This accumulates the arguments passed into an array, after a given index.
+ var restArgs = function(func, startIndex) {
+ startIndex = startIndex == null ? func.length - 1 : +startIndex;
+ return function() {
+ var length = Math.max(arguments.length - startIndex, 0);
+ var rest = Array(length);
+ for (var index = 0; index < length; index++) {
+ rest[index] = arguments[index + startIndex];
+ }
+ switch (startIndex) {
+ case 0: return func.call(this, rest);
+ case 1: return func.call(this, arguments[0], rest);
+ case 2: return func.call(this, arguments[0], arguments[1], rest);
+ }
+ var args = Array(startIndex + 1);
+ for (index = 0; index < startIndex; index++) {
+ args[index] = arguments[index];
+ }
+ args[startIndex] = rest;
+ return func.apply(this, args);
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ var createReduce = function(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ var iterator = function(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ };
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ };
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = restArgs(function(obj, method, args) {
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ });
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior, partition) {
+ return function(obj, iteratee, context) {
+ var result = partition ? [[], []] : {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = group(function(result, value, pass) {
+ result[pass ? 0 : 1].push(value);
+ }, true);
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = restArgs(function(array, otherArrays) {
+ return _.difference(array, otherArrays);
+ });
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ var createPredicateIndexFinder = function(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ };
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ var createIndexFinder = function(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ };
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = restArgs(function(callArgs) {
+ return executeBound(func, bound, context, this, args.concat(callArgs));
+ });
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder by default, allowing any combination of arguments to be
+ // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
+ _.partial = restArgs(function(func, boundArgs) {
+ var placeholder = _.partial.placeholder;
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ });
+
+ _.partial.placeholder = _;
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = restArgs(function(obj, keys) {
+ if (keys.length < 1) throw new Error('bindAll must be passed function names');
+ return _.each(keys, function(key) {
+ obj[key] = _.bind(obj[key], obj);
+ });
+ });
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = restArgs(function(func, wait, args) {
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ });
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ _.restArgs = restArgs;
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ var collectNonEnumProps = function(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ };
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {};
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#x27;',
+ '`': '&#x60;'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = restArgs(function(args) {
+ args.unshift(this._wrapped);
+ return result(this, func.apply(_, args));
+ });
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
diff --git a/openk-platform/openk-theme/src/main/webapp/templates/portal_normal.vm b/openk-platform/openk-theme/src/main/webapp/templates/portal_normal.vm
index 951278dc..88a4e037 100644
--- a/openk-platform/openk-theme/src/main/webapp/templates/portal_normal.vm
+++ b/openk-platform/openk-theme/src/main/webapp/templates/portal_normal.vm
@@ -15,6 +15,7 @@
<link rel="stylesheet" href="$javascript_folder/bootstrap-3.3.4/css/bootstrap.min.css?v=1" type="text/css"/>
<link rel="stylesheet" href="$javascript_folder/bootstrap-3.3.4/css/bootstrap-theme.min.css?v=1" type="text/css"/>
<link rel="stylesheet" href="$javascript_folder/ngAnimate/css/ng-animation.css?v=1" type="text/css"/>
+ <link rel="stylesheet" href="$javascript_folder/macgyver-0.6.1/macgyver.css" type="text/css"/>
<link rel="stylesheet" href="$javascript_folder/../css/additional.css?v=1"/>
@@ -33,10 +34,9 @@
<script src="$javascript_folder/angular-1.3.13/angular.min.js" type="text/javascript"></script>
<script src="$javascript_folder/angular-1.3.13/angular-resource.min.js" type="text/javascript"></script>
<script src="$javascript_folder/ng-grid/ui-grid.min.js" type="text/javascript"></script>
- <script src="$javascript_folder/ngAnimate/js/angular-animate.min.js" type="text/javascript"></script>
- <script src="$javascript_folder/angular-1.3.13/angular-route.min.js" type="text/javascript"></script>
<script src="$javascript_folder/angular-1.3.13/angular-touch.min.js" type="text/javascript"></script>
- <script src="$javascript_folder/ui-bootstrap-0.12.1/ui-bootstrap-0.12.1.min.js" type="text/javascript"></script>
+ <script src="$javascript_folder/underscore-1.8.3/underscore-min.js" type="text/javascript"></script>
+ <script src="$javascript_folder/macgyver-0.6.1/macgyver.min.js" type="text/javascript"></script>
</head>
<body class="$css_class">
diff --git a/openk-platform/openk-theme/src/main/webapp/templates/portlet.vm b/openk-platform/openk-theme/src/main/webapp/templates/portlet.vm
index 43b7f94b..f9dd3098 100644
--- a/openk-platform/openk-theme/src/main/webapp/templates/portlet.vm
+++ b/openk-platform/openk-theme/src/main/webapp/templates/portlet.vm
@@ -4,7 +4,7 @@
#set ($portlet_title = $portlet_display.getTitle())
#set ($portlet_back_url = $htmlUtil.escapeAttribute($portlet_display.getURLBack()))
-<div class="col-xs-12 col-sm-12" style="padding-left:0px;">
+<div class="col-xs-12 col-sm-12" style="">
<section class="portlet" id="portlet_$portlet_id">
@@ -26,7 +26,7 @@
</menu>
</header>
- <div class="portlet-content row maincontent col-sm-12">
+ <div class="row maincontent">
$portlet_display.writeContent($writer)
</div>
</section>

Back to the top