rolodex 2.0.2 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/LICENSE.txt +1 -1
  4. data/bower.json +1 -2
  5. data/dist/rolodex.js +1747 -0
  6. data/dist/rolodex.min.js +1 -0
  7. data/gulpfile.js +57 -0
  8. data/lib/rolodex/version.rb +1 -1
  9. data/package.json +25 -14
  10. data/vendor/assets/javascripts/rolodex_angular/src/dropdown.coffee +5 -1
  11. data/vendor/assets/javascripts/rolodex_angular/src/position.coffee +0 -1
  12. data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion-group.ngt +12 -0
  13. data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion.ngt +1 -0
  14. data/vendor/assets/javascripts/rolodex_angular/template/alert/alert.ngt +4 -0
  15. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/datepicker.ngt +5 -0
  16. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/day.ngt +27 -0
  17. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/month.ngt +30 -0
  18. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/popup.ngt +3 -0
  19. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/year.ngt +30 -0
  20. data/vendor/assets/javascripts/rolodex_angular/template/modal/window.ngt +3 -0
  21. data/vendor/assets/stylesheets/rolodex/components/_forms.sass +1 -0
  22. data/vendor/assets/stylesheets/rolodex/settings/mixins/_svg.sass +3 -1
  23. data/vendor/assets/stylesheets/rolodex/settings/mixins/_typography.sass +2 -4
  24. data/vendor/assets/stylesheets/rolodex/settings/variables/_misc.scss +4 -0
  25. data/vendor/assets/stylesheets/rolodex/settings/variables/_typography.scss +1 -1
  26. metadata +16 -25
  27. data/spec/javascripts/rolodex_angular/modal.spec.coffee +0 -13
  28. data/spec/spec_helper.rb +0 -0
  29. data/spec/test_lib/angular-mocks.js +0 -2173
  30. data/spec/test_lib/angular.js +0 -21883
  31. data/spec/test_lib/jquery-2.1.1.js +0 -9190
  32. data/spec/test_lib/lodash.js +0 -6785
  33. data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion-group.ngt.haml +0 -7
  34. data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion.ngt.haml +0 -1
  35. data/vendor/assets/javascripts/rolodex_angular/template/alert/alert.ngt.haml +0 -3
  36. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/datepicker.ngt.haml +0 -4
  37. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/day.ngt.haml +0 -20
  38. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/month.ngt.haml +0 -17
  39. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/popup.ngt.haml +0 -2
  40. data/vendor/assets/javascripts/rolodex_angular/template/datepicker/year.ngt.haml +0 -17
  41. data/vendor/assets/javascripts/rolodex_angular/template/modal/window.ngt.haml +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 846d3b39bcebe9f004c9f67a7ccccf8dfda90262
4
- data.tar.gz: 97b87caaf47270404bc5007d06f13422ccc0457c
3
+ metadata.gz: cc5ab80dd8fbb098238df00bc298e58c237bf532
4
+ data.tar.gz: 128fd7f70a65e3c122b5c206ab552d419a8e07af
5
5
  SHA512:
6
- metadata.gz: 7be9d59b2f8894523b7568aea79c26f09ff4dd8b5fc97a29dc9c97ddba8d5f502db93ab5faba0d40e6aee995f7ddfa8d839aec42e691f97ef05ba8582a1c6169
7
- data.tar.gz: cafe75eeb0a344643f6a101f1f38569ee8f51f510ab105d2a7ec28118fd1c31fecbb63f7fb921120cf5a37bdee7c79698e2bde9937277bd768239d3749267019
6
+ metadata.gz: 9221629f20c4e102a719524ee166968b699888a718a992347d487be61e5decb005cb8c87393b9f13f09e95c322699f943d7d9f9f4552e180306e87e45b0bfe13
7
+ data.tar.gz: 19fc9ec4421f37a6541968767c91fe69b000ea1c762c40d76d4540a9a218292de05c62fe23d182b9938fe716dc547a5ea3f82cb946471114fe481832613649b2
data/.gitignore CHANGED
@@ -15,6 +15,9 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .tmp
19
+ bower_components/
20
+ node_modules/
18
21
 
19
22
  # Ignore .DS_store file
20
23
  .DS_Store
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Darby Frey
1
+ Copyright (c) 2013 Belly
2
2
 
3
3
  MIT License
4
4
 
data/bower.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "rolodex",
3
- "version": "2.0.2",
4
3
  "homepage": "http://bellycard.com/",
5
4
  "repository": {
6
5
  "type": "git",
7
6
  "url": "https://github.com/bellycard/rolodex"
8
7
  },
9
- "main": "vendor/assets/stylesheets/rolodex.sass",
8
+ "main": "dist/rolodex.min.js",
10
9
  "ignore": [
11
10
  "**/.*",
12
11
  "node_modules",
data/dist/rolodex.js ADDED
@@ -0,0 +1,1747 @@
1
+ (function() {
2
+ angular.module('rolodex', ['templates', 'rolodex.accordion', 'rolodex.alert', 'rolodex.buttons', 'rolodex.datepicker', 'rolodex.dropdown', 'rolodex.modal', 'rolodex.transition']);
3
+
4
+ }).call(this);
5
+
6
+ angular.module("rolodex").run(["$templateCache", function($templateCache) {$templateCache.put("rolodex_angular/template/accordion/accordion-group","<div class=\"panel panel-default\"><div class=\"panel-heading\"><h4 class=\"panel-title\"><a accordion-transclude=\"heading\" class=\"accordion-toggle\" ng-click=\"toggleOpen()\"><span ng-class=\"{\'text-muted\': isDisabled}\">{{heading}}</span></a></h4></div><div class=\"panel-collapse\" collapse=\"!isOpen\"><div class=\"panel-body\" ng-transclude=\"\"></div></div></div>");
7
+ $templateCache.put("rolodex_angular/template/accordion/accordion","<div class=\"panel-group\" ng-transclude=\"\"></div>");
8
+ $templateCache.put("rolodex_angular/template/alert/alert","<div ng-class=\"[\'alert-banner-\' + (type || \'warning\'), closeable ? \'alert-dismissable\' : null]\" role=\"alert\"><button aria-hidden=\"true\" class=\"i-close\" ng-click=\"close()\" ng-show=\"closeable\" type=\"button\">&times;</button><div ng-transclude=\"\"></div></div>");
9
+ $templateCache.put("rolodex_angular/template/datepicker/datepicker","<div ng-keydown=\"keydown($event)\" ng-switch=\"datepickerMode\" role=\"application\"><daypicker ng-switch-when=\"day\" tabindex=\"0\"></daypicker><monthpicker ng-switch-when=\"month\" tabindex=\"0\"></monthpicker><yearpicker ng-switch-when=\"year\" tabindex=\"0\"></yearpicker></div>");
10
+ $templateCache.put("rolodex_angular/template/datepicker/day","<table aria-activedescendant=\"{{ activeDateId }}\" aria-labelledby=\"{{uniqueId }}-title\" role=\"grid\"><thead><tr><th class=\"prev available\" ng-click=\"move(-1)\" tabindex=\"-1\"><div class=\"i-caret\"></div></th><th class=\"month\" colspan=\"{{ 5 + showWeeks }}\">{{ title }}</th><th class=\"next available\" ng-click=\"move(1)\" tabindex=\"-1\"><div class=\"i-caret\"></div></th></tr><tr><th class=\"text-center\" ng-repeat=\"label in labels track by $index\"><small aria-label=\"{{ label.full}}\">{{ label.abbr }}</small></th></tr></thead><tbody><tr ng-repeat=\"row in rows track by $index\"><td aria-disabled=\"{{ !!dt.disabled }}\" id=\"{{ dt.uid }}\" ng-class=\"{active: dt.selected, available: !dt.disabled, off: dt.disabled}\" ng-click=\"select(dt.date, dt.disabled)\" ng-disabled=\"dt.disabled\" ng-repeat=\"dt in row track by dt.date\" role=\"gridcell\" tabindex=\"-1\"><span ng-class=\"{\'text-muted\': dt.secondary}\">{{ dt.label }}</span></td></tr></tbody></table>");
11
+ $templateCache.put("rolodex_angular/template/datepicker/month","<table aria-activedescendant=\"{{ activeDateId }}\" aria-labelledby=\"{{ uniqueId }}-title\" role=\"grid\"><thead><tr><th><button class=\"btn btn-boring pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\" type=\"button\"><i class=\"i-caret\"></i></button></th><th><button aria-atomic=\"true\" aria-live=\"assertive\" class=\"btn btn-boring\" id=\"{{ uniqueId }}-title\" ng-click=\"toggleMode()\" role=\"heading\" style=\"width:100%;\" tabindex=\"-1\" type=\"button\"><strong>{{ title }}</strong></button></th><th><button class=\"btn btn-boring pull-right\" ng-click=\"move(1)\" tabindex=\"-1\" type=\"button\"><i class=\"i-caret\"></i></button></th></tr></thead><tbody><tr ng-repeat=\"row in rows track by $index\"><td aria-disabled=\"{{ !!dt.disabled }}\" class=\"text-center\" id=\"{{ dt.uid }}\" ng-repeat=\"dt in row track by dt.date\" role=\"gridcell\"><button class=\"btn btn-boring\" ng-class=\"{\'btn-info\': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" style=\"width:100%;\" tabindex=\"-1\" type=\"button\"><span ng-class=\"{\'text-info\': dt.current}\">{{ dt.label }}</span></button></td></tr></tbody></table>");
12
+ $templateCache.put("rolodex_angular/template/datepicker/popup","<div class=\"date-picker-solo daterangepicker dropdown-menu group\" data-dropdown-content=\"\" ng-keydown=\"keydown($event)\"><div ng-transclude=\"\"></div></div>");
13
+ $templateCache.put("rolodex_angular/template/datepicker/year","<table aria-activedescendant=\"{{ activeDateId }}\" aria-labelledby=\"{{ uniqueId }}-title\" role=\"grid\"><thead><tr><th><button class=\"btn btn-boring pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\" type=\"button\"><i class=\"i-caret\"></i></button></th><th colspan=\"3\"><button aria-atomic=\"true\" aria-live=\"assertive\" class=\"btn btn-boring\" id=\"{{ uniqueId }}-title\" ng-click=\"toggleMode()\" role=\"heading\" style=\"width:100%;\" tabindex=\"-1\" type=\"button\"><strong>{{ title }}</strong></button></th><th><button class=\"btn btn-boring pull-right\" ng-click=\"move(1)\" tabindex=\"-1\" type=\"button\"><i class=\"i-caret\"></i></button></th></tr></thead><tbody><tr ng-repeat=\"row in rows track by $index\"><td aria-disabled=\"{{ !!dt.disabled }}\" class=\"text-center\" id=\"{{ dt.uid }}\" ng-repeat=\"dt in row track by dt.date\" role=\"gridcell\"><button class=\"btn btn-boring\" ng-class=\"{\'btn-info\': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" style=\"width:100%;\" tabindex=\"-1\" type=\"button\"><span ng-class=\"{\'text-info\': dt.current}\">{{ dt.label }}</span></button></td></tr></tbody></table>");
14
+ $templateCache.put("rolodex_angular/template/modal/window","<div class=\"modal\" ng-class=\"{\'modal-fade\': animate}\" ng-click=\"close($event)\" role=\"dialog\" tabindex=\"-1\"><div class=\"modal-content\" modal-transclude=\"\"></div></div>");}]);
15
+ (function() { angular.module('templates', []); }).call(this);
16
+ (function() {
17
+ angular.module("rolodex.accordion", ["rolodex.collapse"]).constant("accordionConfig", {
18
+ closeOthers: true
19
+ }).controller("AccordionController", [
20
+ "$scope", "$attrs", "accordionConfig", function($scope, $attrs, accordionConfig) {
21
+ this.groups = [];
22
+ this.closeOthers = function(openGroup) {
23
+ var closeOthers;
24
+ closeOthers = (angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers);
25
+ if (closeOthers) {
26
+ return angular.forEach(this.groups, function(group) {
27
+ if (group !== openGroup) {
28
+ return group.isOpen = false;
29
+ }
30
+ });
31
+ }
32
+ };
33
+ this.addGroup = function(groupScope) {
34
+ var that;
35
+ that = this;
36
+ this.groups.push(groupScope);
37
+ return groupScope.$on("$destroy", function(event) {
38
+ return that.removeGroup(groupScope);
39
+ });
40
+ };
41
+ this.removeGroup = function(group) {
42
+ var index;
43
+ index = this.groups.indexOf(group);
44
+ if (index !== -1) {
45
+ return this.groups.splice(index, 1);
46
+ }
47
+ };
48
+ return this;
49
+ }
50
+ ]).directive("accordion", function() {
51
+ return {
52
+ restrict: "EA",
53
+ controller: "AccordionController",
54
+ transclude: true,
55
+ replace: false,
56
+ templateUrl: 'rolodex_angular/template/accordion/accordion'
57
+ };
58
+ }).directive("accordionGroup", function() {
59
+ return {
60
+ require: "^accordion",
61
+ restrict: "EA",
62
+ transclude: true,
63
+ replace: true,
64
+ templateUrl: 'rolodex_angular/template/accordion/accordion-group',
65
+ scope: {
66
+ heading: "@",
67
+ isOpen: "=?",
68
+ isDisabled: "=?"
69
+ },
70
+ controller: function() {
71
+ return this.setHeading = function(element) {
72
+ return this.heading = element;
73
+ };
74
+ },
75
+ link: function(scope, element, attrs, accordionCtrl) {
76
+ accordionCtrl.addGroup(scope);
77
+ scope.$watch("isOpen", function(value) {
78
+ if (value) {
79
+ accordionCtrl.closeOthers(scope);
80
+ }
81
+ });
82
+ return scope.toggleOpen = function() {
83
+ if (!scope.isDisabled) {
84
+ return scope.isOpen = !scope.isOpen;
85
+ }
86
+ };
87
+ }
88
+ };
89
+ }).directive("accordionHeading", function() {
90
+ return {
91
+ restrict: "EA",
92
+ transclude: true,
93
+ template: "",
94
+ replace: true,
95
+ require: "^accordionGroup",
96
+ link: function(scope, element, attr, accordionGroupCtrl, transclude) {
97
+ return accordionGroupCtrl.setHeading(transclude(scope, (function() {})));
98
+ }
99
+ };
100
+ }).directive("accordionTransclude", function() {
101
+ return {
102
+ require: "^accordionGroup",
103
+ link: function(scope, element, attr, controller) {
104
+ return scope.$watch((function() {
105
+ return controller[attr.accordionTransclude];
106
+ }), function(heading) {
107
+ if (heading) {
108
+ element.html("");
109
+ return element.append(heading);
110
+ }
111
+ });
112
+ }
113
+ };
114
+ });
115
+
116
+ }).call(this);
117
+
118
+ (function() {
119
+ angular.module('rolodex.alert', []).controller('AlertController', [
120
+ '$scope', '$attrs', function($scope, $attrs) {
121
+ return $scope.closeable = 'close' in $attrs;
122
+ }
123
+ ]).directive('alert', function() {
124
+ return {
125
+ restrict: 'EA',
126
+ controller: 'AlertController',
127
+ templateUrl: 'rolodex_angular/template/alert/alert',
128
+ transclude: true,
129
+ replace: true,
130
+ scope: {
131
+ type: '@',
132
+ close: '&'
133
+ }
134
+ };
135
+ });
136
+
137
+ }).call(this);
138
+
139
+ (function() {
140
+ angular.module("rolodex.buttons", []).constant("buttonConfig", {
141
+ activeClass: "active",
142
+ toggleEvent: "click"
143
+ }).controller("ButtonsController", [
144
+ "buttonConfig", function(buttonConfig) {
145
+ this.activeClass = buttonConfig.activeClass || "active";
146
+ this.toggleEvent = buttonConfig.toggleEvent || "click";
147
+ return this;
148
+ }
149
+ ]).directive("btnRadio", function() {
150
+ return {
151
+ require: ["btnRadio", "ngModel"],
152
+ controller: "ButtonsController",
153
+ link: function(scope, element, attrs, ctrls) {
154
+ var buttonsCtrl, ngModelCtrl;
155
+ buttonsCtrl = ctrls[0];
156
+ ngModelCtrl = ctrls[1];
157
+ ngModelCtrl.$render = function() {
158
+ return element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
159
+ };
160
+ return element.bind(buttonsCtrl.toggleEvent, function() {
161
+ var isActive;
162
+ isActive = element.hasClass(buttonsCtrl.activeClass);
163
+ if (!isActive || angular.isDefined(attrs.uncheckable)) {
164
+ return scope.$apply(function() {
165
+ ngModelCtrl.$setViewValue((isActive ? null : scope.$eval(attrs.btnRadio)));
166
+ return ngModelCtrl.$render();
167
+ });
168
+ }
169
+ });
170
+ }
171
+ };
172
+ }).directive("btnCheckbox", function() {
173
+ return {
174
+ require: ["btnCheckbox", "ngModel"],
175
+ controller: "ButtonsController",
176
+ link: function(scope, element, attrs, ctrls) {
177
+ var buttonsCtrl, getCheckboxValue, getFalseValue, getTrueValue, ngModelCtrl;
178
+ getTrueValue = function() {
179
+ return getCheckboxValue(attrs.btnCheckboxTrue, true);
180
+ };
181
+ getFalseValue = function() {
182
+ return getCheckboxValue(attrs.btnCheckboxFalse, false);
183
+ };
184
+ getCheckboxValue = function(attributeValue, defaultValue) {
185
+ var val;
186
+ val = scope.$eval(attributeValue);
187
+ if (angular.isDefined(val)) {
188
+ return val;
189
+ } else {
190
+ return defaultValue;
191
+ }
192
+ };
193
+ buttonsCtrl = ctrls[0];
194
+ ngModelCtrl = ctrls[1];
195
+ ngModelCtrl.$render = function() {
196
+ return element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
197
+ };
198
+ return element.bind(buttonsCtrl.toggleEvent, function() {
199
+ return scope.$apply(function() {
200
+ ngModelCtrl.$setViewValue((element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()));
201
+ return ngModelCtrl.$render();
202
+ });
203
+ });
204
+ }
205
+ };
206
+ });
207
+
208
+ }).call(this);
209
+
210
+ (function() {
211
+ angular.module("rolodex.collapse", ["rolodex.transition"]).directive("collapse", [
212
+ "$transition", function($transition) {
213
+ return {
214
+ link: function(scope, element, attrs) {
215
+ var collapse, collapseDone, currentTransition, doTransition, expand, expandDone, initialAnimSkip;
216
+ doTransition = function(change) {
217
+ var currentTransition, newTransition, newTransitionDone;
218
+ newTransitionDone = function() {
219
+ var currentTransition;
220
+ if (currentTransition === newTransition) {
221
+ return currentTransition = undefined;
222
+ }
223
+ };
224
+ newTransition = $transition(element, change);
225
+ if (currentTransition) {
226
+ currentTransition.cancel();
227
+ }
228
+ currentTransition = newTransition;
229
+ newTransition.then(newTransitionDone, newTransitionDone);
230
+ return newTransition;
231
+ };
232
+ expand = function() {
233
+ var initialAnimSkip;
234
+ if (initialAnimSkip) {
235
+ initialAnimSkip = false;
236
+ expandDone();
237
+ } else {
238
+ element.removeClass("collapse").addClass("collapsing");
239
+ doTransition({
240
+ height: element[0].scrollHeight + "px"
241
+ }).then(expandDone);
242
+ }
243
+ };
244
+ expandDone = function() {
245
+ element.removeClass("collapsing");
246
+ element.addClass("collapse in");
247
+ element.css({
248
+ height: "auto"
249
+ });
250
+ };
251
+ collapse = function() {
252
+ var initialAnimSkip, x;
253
+ if (initialAnimSkip) {
254
+ initialAnimSkip = false;
255
+ collapseDone();
256
+ element.css({
257
+ height: 0
258
+ });
259
+ } else {
260
+ element.css({
261
+ height: element[0].scrollHeight + "px"
262
+ });
263
+ x = element[0].offsetWidth;
264
+ element.removeClass("collapse in").addClass("collapsing");
265
+ doTransition({
266
+ height: 0
267
+ }).then(collapseDone);
268
+ }
269
+ };
270
+ collapseDone = function() {
271
+ element.removeClass("collapsing");
272
+ element.addClass("collapse");
273
+ };
274
+ initialAnimSkip = true;
275
+ currentTransition = void 0;
276
+ scope.$watch(attrs.collapse, function(shouldCollapse) {
277
+ if (shouldCollapse) {
278
+ collapse();
279
+ } else {
280
+ expand();
281
+ }
282
+ });
283
+ }
284
+ };
285
+ }
286
+ ]);
287
+
288
+ }).call(this);
289
+
290
+ (function() {
291
+ angular.module('rolodex.dateparser', []).service("dateParser", [
292
+ "$locale", "orderByFilter", function($locale, orderByFilter) {
293
+ var createParser, formatCodeToRegex, isValid;
294
+ createParser = function(format) {
295
+ var map, regex;
296
+ map = [];
297
+ regex = format.split("");
298
+ angular.forEach(formatCodeToRegex, function(data, code) {
299
+ var i, index, n;
300
+ index = format.indexOf(code);
301
+ if (index > -1) {
302
+ format = format.split("");
303
+ regex[index] = "(" + data.regex + ")";
304
+ format[index] = "$";
305
+ i = index + 1;
306
+ n = index + code.length;
307
+ while (i < n) {
308
+ regex[i] = "";
309
+ format[i] = "$";
310
+ i++;
311
+ }
312
+ format = format.join("");
313
+ map.push({
314
+ index: index,
315
+ apply: data.apply
316
+ });
317
+ }
318
+ });
319
+ return {
320
+ regex: new RegExp("^" + regex.join("") + "$"),
321
+ map: orderByFilter(map, "index")
322
+ };
323
+ };
324
+ isValid = function(year, month, date) {
325
+ if (month === 1 && date > 28) {
326
+ return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
327
+ }
328
+ if (month === 3 || month === 5 || month === 8 || month === 10) {
329
+ return date < 31;
330
+ }
331
+ return true;
332
+ };
333
+ this.parsers = {};
334
+ formatCodeToRegex = {
335
+ yyyy: {
336
+ regex: "\\d{4}",
337
+ apply: function(value) {
338
+ this.year = +value;
339
+ }
340
+ },
341
+ yy: {
342
+ regex: "\\d{2}",
343
+ apply: function(value) {
344
+ this.year = +value + 2000;
345
+ }
346
+ },
347
+ y: {
348
+ regex: "\\d{1,4}",
349
+ apply: function(value) {
350
+ this.year = +value;
351
+ }
352
+ },
353
+ MMMM: {
354
+ regex: $locale.DATETIME_FORMATS.MONTH.join("|"),
355
+ apply: function(value) {
356
+ this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value);
357
+ }
358
+ },
359
+ MMM: {
360
+ regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|"),
361
+ apply: function(value) {
362
+ this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value);
363
+ }
364
+ },
365
+ MM: {
366
+ regex: "0[1-9]|1[0-2]",
367
+ apply: function(value) {
368
+ this.month = value - 1;
369
+ }
370
+ },
371
+ M: {
372
+ regex: "[1-9]|1[0-2]",
373
+ apply: function(value) {
374
+ this.month = value - 1;
375
+ }
376
+ },
377
+ dd: {
378
+ regex: "[0-2][0-9]{1}|3[0-1]{1}",
379
+ apply: function(value) {
380
+ this.date = +value;
381
+ }
382
+ },
383
+ d: {
384
+ regex: "[1-2]?[0-9]{1}|3[0-1]{1}",
385
+ apply: function(value) {
386
+ return this.date = +value;
387
+ }
388
+ },
389
+ EEEE: {
390
+ regex: $locale.DATETIME_FORMATS.DAY.join("|")
391
+ },
392
+ EEE: {
393
+ regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|")
394
+ }
395
+ };
396
+ return this.parse = function(input, format) {
397
+ var dt, fields, i, map, mapper, n, parser, regex, results;
398
+ if (!angular.isString(input) || !format) {
399
+ return input;
400
+ }
401
+ format = $locale.DATETIME_FORMATS[format] || format;
402
+ if (!this.parsers[format]) {
403
+ this.parsers[format] = createParser(format);
404
+ }
405
+ parser = this.parsers[format];
406
+ regex = parser.regex;
407
+ map = parser.map;
408
+ results = input.match(regex);
409
+ if (results && results.length) {
410
+ fields = {
411
+ year: 1900,
412
+ month: 0,
413
+ date: 1,
414
+ hours: 0
415
+ };
416
+ dt = void 0;
417
+ i = 1;
418
+ n = results.length;
419
+ while (i < n) {
420
+ mapper = map[i - 1];
421
+ if (mapper.apply) {
422
+ mapper.apply.call(fields, results[i]);
423
+ }
424
+ i++;
425
+ }
426
+ if (isValid(fields.year, fields.month, fields.date)) {
427
+ dt = new Date(fields.year, fields.month, fields.date, fields.hours);
428
+ }
429
+ return dt;
430
+ }
431
+ };
432
+ }
433
+ ]);
434
+
435
+ }).call(this);
436
+
437
+ (function() {
438
+ angular.module('rolodex.datepicker', ['rolodex.dateparser', 'rolodex.dropdown', 'rolodex.position']).constant('datepickerConfig', {
439
+ formatDay: 'd',
440
+ formatMonth: 'MMMM',
441
+ formatYear: 'yyyy',
442
+ formatDayHeader: 'EEE',
443
+ formatDayTitle: 'MMMM yyyy',
444
+ formatMonthTitle: 'yyyy',
445
+ datepickerMode: 'day',
446
+ minMode: 'day',
447
+ maxMode: 'year',
448
+ showWeeks: true,
449
+ startingDay: 0,
450
+ yearRange: 20,
451
+ minDate: null,
452
+ maxDate: null
453
+ }).controller('DatepickerController', [
454
+ '$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) {
455
+ var focusElement, ngModelCtrl, self;
456
+ self = this;
457
+ ngModelCtrl = {
458
+ $setViewValue: angular.noop
459
+ };
460
+ this.modes = ['day', 'month', 'year'];
461
+ angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function(key, index) {
462
+ self[key] = (angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key]);
463
+ });
464
+ angular.forEach(['minDate', 'maxDate'], function(key) {
465
+ if ($attrs[key]) {
466
+ return $scope.$parent.$watch($parse($attrs[key]), function(value) {
467
+ self[key] = (value ? new Date(value) : null);
468
+ return self.refreshView();
469
+ });
470
+ } else {
471
+ return self[key] = (datepickerConfig[key] ? new Date(datepickerConfig[key]) : null);
472
+ }
473
+ });
474
+ $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;
475
+ $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
476
+ this.activeDate = (angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date());
477
+ this.init = function(ngModelCtrl_) {
478
+ ngModelCtrl = ngModelCtrl_;
479
+ return ngModelCtrl.$render = function() {
480
+ return self.render();
481
+ };
482
+ };
483
+ this.render = function() {
484
+ var date, isValid;
485
+ if (ngModelCtrl.$modelValue) {
486
+ date = new Date(ngModelCtrl.$modelValue);
487
+ isValid = !isNaN(date);
488
+ if (isValid) {
489
+ this.activeDate = date;
490
+ } else {
491
+ $log.error('Datepicker directive: \'ng-model\' value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
492
+ }
493
+ ngModelCtrl.$setValidity('date', isValid);
494
+ }
495
+ return this.refreshView();
496
+ };
497
+ this.refreshView = function() {
498
+ var date;
499
+ if (this.element) {
500
+ this._refreshView();
501
+ date = (ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null);
502
+ return ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));
503
+ }
504
+ };
505
+ this.createDateObject = function(date, format) {
506
+ var model;
507
+ model = (ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null);
508
+ return {
509
+ date: date,
510
+ label: dateFilter(date, format),
511
+ selected: model && this.compare(date, model) === 0,
512
+ disabled: this.isDisabled(date),
513
+ current: this.compare(date, new Date()) === 0
514
+ };
515
+ };
516
+ this.isDisabled = function(date) {
517
+ return (this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({
518
+ date: date,
519
+ mode: $scope.datepickerMode
520
+ }));
521
+ };
522
+ this.split = function(arr, size) {
523
+ var arrays;
524
+ arrays = [];
525
+ while (arr.length > 0) {
526
+ arrays.push(arr.splice(0, size));
527
+ }
528
+ return arrays;
529
+ };
530
+ $scope.select = (function(_this) {
531
+ return function(date) {
532
+ var dt;
533
+ if (_this.isDisabled(date)) {
534
+ return;
535
+ }
536
+ if ($scope.datepickerMode === self.minMode) {
537
+ dt = (ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date(0, 0, 0, 0, 0, 0, 0));
538
+ dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
539
+ ngModelCtrl.$setViewValue(dt);
540
+ return ngModelCtrl.$render();
541
+ } else {
542
+ self.activeDate = date;
543
+ return $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1];
544
+ }
545
+ };
546
+ })(this);
547
+ $scope.move = function(direction) {
548
+ var month, year;
549
+ year = self.activeDate.getFullYear() + direction * (self.step.years || 0);
550
+ month = self.activeDate.getMonth() + direction * (self.step.months || 0);
551
+ self.activeDate.setFullYear(year, month, 1);
552
+ return self.refreshView();
553
+ };
554
+ $scope.toggleMode = function(direction) {
555
+ direction = direction || 1;
556
+ if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {
557
+ return;
558
+ }
559
+ return $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction];
560
+ };
561
+ $scope.keys = {
562
+ 13: 'enter',
563
+ 32: 'space',
564
+ 33: 'pageup',
565
+ 34: 'pagedown',
566
+ 35: 'end',
567
+ 36: 'home',
568
+ 37: 'left',
569
+ 38: 'up',
570
+ 39: 'right',
571
+ 40: 'down'
572
+ };
573
+ focusElement = function() {
574
+ return $timeout((function() {
575
+ return self.element[0].focus();
576
+ }), 0, false);
577
+ };
578
+ $scope.$on('datepicker.focus', focusElement);
579
+ $scope.keydown = function(evt) {
580
+ var key;
581
+ key = $scope.keys[evt.which];
582
+ if (!key || evt.shiftKey || evt.altKey) {
583
+ return;
584
+ }
585
+ evt.preventDefault();
586
+ evt.stopPropagation();
587
+ if (key === 'enter' || key === 'space') {
588
+ if (self.isDisabled(self.activeDate)) {
589
+ return;
590
+ }
591
+ $scope.select(self.activeDate);
592
+ return focusElement();
593
+ } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
594
+ $scope.toggleMode((key === 'up' ? 1 : -1));
595
+ return focusElement();
596
+ } else {
597
+ self.handleKeyDown(key, evt);
598
+ return self.refreshView();
599
+ }
600
+ };
601
+ return this;
602
+ }
603
+ ]).directive('datepicker', function() {
604
+ return {
605
+ restrict: 'EA',
606
+ replace: true,
607
+ templateUrl: 'rolodex_angular/template/datepicker/datepicker',
608
+ scope: {
609
+ datepickerMode: '=?',
610
+ dateDisabled: '&'
611
+ },
612
+ require: ['datepicker', '?^ngModel'],
613
+ controller: 'DatepickerController',
614
+ link: function(scope, element, attrs, ctrls) {
615
+ var datepickerCtrl, ngModelCtrl;
616
+ datepickerCtrl = ctrls[0];
617
+ ngModelCtrl = ctrls[1];
618
+ if (ngModelCtrl) {
619
+ return datepickerCtrl.init(ngModelCtrl);
620
+ }
621
+ }
622
+ };
623
+ }).directive('daypicker', [
624
+ 'dateFilter', function(dateFilter) {
625
+ return {
626
+ restrict: 'EA',
627
+ replace: true,
628
+ templateUrl: 'rolodex_angular/template/datepicker/day',
629
+ require: '^datepicker',
630
+ link: function(scope, element, attrs, ctrl) {
631
+ var DAYS_IN_MONTH, getDates, getDaysInMonth, getISO8601WeekNumber;
632
+ getDaysInMonth = function(year, month) {
633
+ if ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) {
634
+ return 29;
635
+ } else {
636
+ return DAYS_IN_MONTH[month];
637
+ }
638
+ };
639
+ getDates = function(startDate, n) {
640
+ var current, dates, i;
641
+ dates = new Array(n);
642
+ current = new Date(startDate);
643
+ i = 0;
644
+ current.setHours(12);
645
+ while (i < n) {
646
+ dates[i++] = new Date(current);
647
+ current.setDate(current.getDate() + 1);
648
+ }
649
+ return dates;
650
+ };
651
+ getISO8601WeekNumber = function(date) {
652
+ var checkDate, time;
653
+ checkDate = new Date(date);
654
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
655
+ time = checkDate.getTime();
656
+ checkDate.setMonth(0);
657
+ checkDate.setDate(1);
658
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
659
+ };
660
+ scope.showWeeks = ctrl.showWeeks;
661
+ ctrl.step = {
662
+ months: 1
663
+ };
664
+ ctrl.element = element;
665
+ DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
666
+ ctrl._refreshView = function() {
667
+ var days, difference, firstDate, firstDayOfMonth, i, j, month, numDisplayedFromPreviousMonth, numWeeks, results, weekNumber, year;
668
+ year = ctrl.activeDate.getFullYear();
669
+ month = ctrl.activeDate.getMonth();
670
+ firstDayOfMonth = new Date(year, month, 1);
671
+ difference = ctrl.startingDay - firstDayOfMonth.getDay();
672
+ numDisplayedFromPreviousMonth = (difference > 0 ? 7 - difference : -difference);
673
+ firstDate = new Date(firstDayOfMonth);
674
+ if (numDisplayedFromPreviousMonth > 0) {
675
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
676
+ }
677
+ days = getDates(firstDate, 42);
678
+ i = 0;
679
+ while (i < 42) {
680
+ days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {
681
+ secondary: days[i].getMonth() !== month,
682
+ uid: scope.uniqueId + '-' + i
683
+ });
684
+ i++;
685
+ }
686
+ scope.labels = new Array(7);
687
+ j = 0;
688
+ while (j < 7) {
689
+ scope.labels[j] = {
690
+ abbr: dateFilter(days[j].date, ctrl.formatDayHeader).substr(0, 2),
691
+ full: dateFilter(days[j].date, 'EEEE')
692
+ };
693
+ j++;
694
+ }
695
+ scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);
696
+ scope.rows = ctrl.split(days, 7);
697
+ if (scope.showWeeks) {
698
+ scope.weekNumbers = [];
699
+ weekNumber = getISO8601WeekNumber(scope.rows[0][0].date);
700
+ numWeeks = scope.rows.length;
701
+ results = [];
702
+ while (scope.weekNumbers.push(weekNumber++) < numWeeks) {
703
+ continue;
704
+ }
705
+ return results;
706
+ }
707
+ };
708
+ ctrl.compare = function(date1, date2) {
709
+ return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
710
+ };
711
+ ctrl.handleKeyDown = function(key, evt) {
712
+ var date, month;
713
+ date = ctrl.activeDate.getDate();
714
+ if (key === 'left') {
715
+ date = date - 1;
716
+ } else if (key === 'up') {
717
+ date = date - 7;
718
+ } else if (key === 'right') {
719
+ date = date + 1;
720
+ } else if (key === 'down') {
721
+ date = date + 7;
722
+ } else if (key === 'pageup' || key === 'pagedown') {
723
+ month = ctrl.activeDate.getMonth() + (key === 'pageup' ? -1 : 1);
724
+ ctrl.activeDate.setMonth(month, 1);
725
+ date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date);
726
+ } else if (key === 'home') {
727
+ date = 1;
728
+ } else {
729
+ if (key === 'end') {
730
+ date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth());
731
+ }
732
+ }
733
+ return ctrl.activeDate.setDate(date);
734
+ };
735
+ return ctrl.refreshView();
736
+ }
737
+ };
738
+ }
739
+ ]).directive('monthpicker', [
740
+ 'dateFilter', function(dateFilter) {
741
+ return {
742
+ restrict: 'EA',
743
+ replace: true,
744
+ templateUrl: 'rolodex_angular/template/datepicker/month',
745
+ require: '^datepicker',
746
+ link: function(scope, element, attrs, ctrl) {
747
+ ctrl.step = {
748
+ years: 1
749
+ };
750
+ ctrl.element = element;
751
+ ctrl._refreshView = function() {
752
+ var i, months, year;
753
+ months = new Array(12);
754
+ year = ctrl.activeDate.getFullYear();
755
+ i = 0;
756
+ while (i < 12) {
757
+ months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), {
758
+ uid: scope.uniqueId + '-' + i
759
+ });
760
+ i++;
761
+ }
762
+ scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle);
763
+ return scope.rows = ctrl.split(months, 3);
764
+ };
765
+ ctrl.compare = function(date1, date2) {
766
+ return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth());
767
+ };
768
+ ctrl.handleKeyDown = function(key, evt) {
769
+ var date, year;
770
+ date = ctrl.activeDate.getMonth();
771
+ if (key === 'left') {
772
+ date = date - 1;
773
+ } else if (key === 'up') {
774
+ date = date - 3;
775
+ } else if (key === 'right') {
776
+ date = date + 1;
777
+ } else if (key === 'down') {
778
+ date = date + 3;
779
+ } else if (key === 'pageup' || key === 'pagedown') {
780
+ year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? -1 : 1);
781
+ ctrl.activeDate.setFullYear(year);
782
+ } else if (key === 'home') {
783
+ date = 0;
784
+ } else {
785
+ if (key === 'end') {
786
+ date = 11;
787
+ }
788
+ }
789
+ return ctrl.activeDate.setMonth(date);
790
+ };
791
+ return ctrl.refreshView();
792
+ }
793
+ };
794
+ }
795
+ ]).directive('yearpicker', [
796
+ 'dateFilter', function(dateFilter) {
797
+ return {
798
+ restrict: 'EA',
799
+ replace: true,
800
+ templateUrl: 'rolodex_angular/template/datepicker/year',
801
+ require: '^datepicker',
802
+ link: function(scope, element, attrs, ctrl) {
803
+ var getStartingYear, range;
804
+ getStartingYear = function(year) {
805
+ return parseInt((year - 1) / range, 10) * range + 1;
806
+ };
807
+ range = ctrl.yearRange;
808
+ ctrl.step = {
809
+ years: range
810
+ };
811
+ ctrl.element = element;
812
+ ctrl._refreshView = function() {
813
+ var i, start, years;
814
+ years = new Array(range);
815
+ i = 0;
816
+ start = getStartingYear(ctrl.activeDate.getFullYear());
817
+ while (i < range) {
818
+ years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), {
819
+ uid: scope.uniqueId + '-' + i
820
+ });
821
+ i++;
822
+ }
823
+ scope.title = [years[0].label, years[range - 1].label].join(' - ');
824
+ return scope.rows = ctrl.split(years, 5);
825
+ };
826
+ ctrl.compare = function(date1, date2) {
827
+ return date1.getFullYear() - date2.getFullYear();
828
+ };
829
+ ctrl.handleKeyDown = function(key, evt) {
830
+ var date;
831
+ date = ctrl.activeDate.getFullYear();
832
+ if (key === 'left') {
833
+ date = date - 1;
834
+ } else if (key === 'up') {
835
+ date = date - 5;
836
+ } else if (key === 'right') {
837
+ date = date + 1;
838
+ } else if (key === 'down') {
839
+ date = date + 5;
840
+ } else if (key === 'pageup' || key === 'pagedown') {
841
+ date += (key === 'pageup' ? -1 : 1) * ctrl.step.years;
842
+ } else if (key === 'home') {
843
+ date = getStartingYear(ctrl.activeDate.getFullYear());
844
+ } else {
845
+ if (key === 'end') {
846
+ date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1;
847
+ }
848
+ }
849
+ return ctrl.activeDate.setFullYear(date);
850
+ };
851
+ return ctrl.refreshView();
852
+ }
853
+ };
854
+ }
855
+ ]).constant('datepickerPopupConfig', {
856
+ datepickerPopup: 'yyyy-MM-dd',
857
+ currentText: 'Today',
858
+ clearText: 'Clear',
859
+ closeText: 'Done',
860
+ closeOnDateSelection: true,
861
+ appendToBody: false,
862
+ showButtonBar: true
863
+ }).directive('datepickerPopup', [
864
+ '$compile', '$parse', '$document', 'dateFilter', 'dateParser', 'datepickerPopupConfig', 'dropdownService', function($compile, $parse, $document, dateFilter, dateParser, datepickerPopupConfig, dropdownService) {
865
+ return {
866
+ restrict: 'EA',
867
+ require: 'ngModel',
868
+ scope: {
869
+ isOpen: '=?',
870
+ currentText: '@',
871
+ clearText: '@',
872
+ closeText: '@',
873
+ dateDisabled: '&'
874
+ },
875
+ link: function(scope, element, attrs, ngModel) {
876
+ var $popup, appendToBody, cameltoDash, closeOnDateSelection, dateFormat, datepickerEl, parseDate, popupEl;
877
+ cameltoDash = function(string) {
878
+ return string.replace(/([A-Z])/g, function($1) {
879
+ return '-' + $1.toLowerCase();
880
+ });
881
+ };
882
+ parseDate = function(viewValue) {
883
+ var date;
884
+ if (!viewValue) {
885
+ ngModel.$setValidity('date', true);
886
+ return null;
887
+ } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {
888
+ ngModel.$setValidity('date', true);
889
+ return viewValue;
890
+ } else if (angular.isString(viewValue)) {
891
+ date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue);
892
+ if (isNaN(date)) {
893
+ ngModel.$setValidity('date', false);
894
+ return undefined;
895
+ } else {
896
+ ngModel.$setValidity('date', true);
897
+ return date;
898
+ }
899
+ } else {
900
+ ngModel.$setValidity('date', false);
901
+ return undefined;
902
+ }
903
+ };
904
+ dateFormat = void 0;
905
+ closeOnDateSelection = (angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection);
906
+ appendToBody = (angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody);
907
+ scope.showButtonBar = (angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar);
908
+ scope.getText = function(key) {
909
+ return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
910
+ };
911
+ attrs.$observe('datepickerPopup', function(value) {
912
+ dateFormat = value || datepickerPopupConfig.datepickerPopup;
913
+ return ngModel.$render();
914
+ });
915
+ popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
916
+ popupEl.attr({
917
+ 'ng-model': 'date',
918
+ 'ng-change': 'dateSelection()'
919
+ });
920
+ datepickerEl = angular.element(popupEl.children()[0]);
921
+ if (attrs.datepickerOptions) {
922
+ angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function(value, option) {
923
+ return datepickerEl.attr(cameltoDash(option), value);
924
+ });
925
+ }
926
+ scope.watchData = {};
927
+ angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function(key) {
928
+ var getAttribute, setAttribute;
929
+ if (attrs[key]) {
930
+ getAttribute = $parse(attrs[key]);
931
+ scope.$parent.$watch(getAttribute, function(value) {
932
+ return scope.watchData[key] = value;
933
+ });
934
+ datepickerEl.attr(cameltoDash(key), 'watchData.' + key);
935
+ if (key === 'datepickerMode') {
936
+ setAttribute = getAttribute.assign;
937
+ return scope.$watch('watchData.' + key, function(value, oldvalue) {
938
+ if (value !== oldvalue) {
939
+ return setAttribute(scope.$parent, value);
940
+ }
941
+ });
942
+ }
943
+ }
944
+ });
945
+ if (attrs.dateDisabled) {
946
+ datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');
947
+ }
948
+ ngModel.$parsers.unshift(parseDate);
949
+ scope.dateSelection = function(dt) {
950
+ if (angular.isDefined(dt)) {
951
+ scope.date = dt;
952
+ }
953
+ ngModel.$setViewValue(scope.date);
954
+ ngModel.$render();
955
+ if (closeOnDateSelection) {
956
+ scope.isOpen = false;
957
+ scope.forceClose = true;
958
+ dropdownService.close(scope);
959
+ return element[0].focus();
960
+ }
961
+ };
962
+ element.bind('input change keyup', function() {
963
+ return scope.$apply(function() {
964
+ return scope.date = ngModel.$modelValue;
965
+ });
966
+ });
967
+ ngModel.$render = function() {
968
+ var date;
969
+ date = (ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '');
970
+ element.val(date);
971
+ return scope.date = parseDate(ngModel.$modelValue);
972
+ };
973
+ scope.select = function(date) {
974
+ var today;
975
+ if (date === 'today') {
976
+ today = new Date();
977
+ if (angular.isDate(ngModel.$modelValue)) {
978
+ date = new Date(ngModel.$modelValue);
979
+ date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
980
+ } else {
981
+ date = new Date(today.setHours(0, 0, 0, 0));
982
+ }
983
+ }
984
+ return scope.dateSelection(date);
985
+ };
986
+ $popup = $compile(popupEl)(scope);
987
+ if (appendToBody) {
988
+ $document.find('body').append($popup);
989
+ } else {
990
+ element.after($popup);
991
+ }
992
+ return scope.$on('$destroy', function() {
993
+ return $popup.remove();
994
+ });
995
+ }
996
+ };
997
+ }
998
+ ]).directive('datepickerPopupWrap', function() {
999
+ return {
1000
+ restrict: 'EA',
1001
+ replace: true,
1002
+ transclude: true,
1003
+ templateUrl: 'rolodex_angular/template/datepicker/popup',
1004
+ link: function(scope, element, attrs) {
1005
+ return element.bind('click', function(event) {
1006
+ event.preventDefault();
1007
+ return event.stopPropagation();
1008
+ });
1009
+ }
1010
+ };
1011
+ });
1012
+
1013
+ }).call(this);
1014
+
1015
+ (function() {
1016
+ angular.module('rolodex.dropdown', []).constant('dropdownConfig', {
1017
+ dropDownOpen: 'data-dropdown-open'
1018
+ }).service('dropdownService', [
1019
+ '$document', '$timeout', function($document, $timeout) {
1020
+ var closeDropdown, escapeKeyBind, openScope;
1021
+ openScope = null;
1022
+ this.open = function(dropdownScope) {
1023
+ if (!openScope) {
1024
+ $document.bind('click', closeDropdown);
1025
+ $document.bind('keydown', escapeKeyBind);
1026
+ }
1027
+ if (openScope && openScope !== dropdownScope) {
1028
+ openScope.isOpen = false;
1029
+ }
1030
+ return openScope = dropdownScope;
1031
+ };
1032
+ this.close = function(dropdownScope) {
1033
+ if (openScope === dropdownScope || dropdownScope.forceClose) {
1034
+ if (dropdownScope.forceClose) {
1035
+ if (openScope) {
1036
+ openScope.isOpen = false;
1037
+ }
1038
+ $timeout(function() {
1039
+ return dropdownScope.isOpen = false;
1040
+ });
1041
+ }
1042
+ openScope = null;
1043
+ $document.unbind('click', closeDropdown);
1044
+ return $document.unbind('keydown', escapeKeyBind);
1045
+ }
1046
+ };
1047
+ closeDropdown = function(evt) {
1048
+ var toggleElement;
1049
+ toggleElement = openScope.getToggleElement();
1050
+ if (evt && (toggleElement != null ? toggleElement[0].contains(evt.target) : void 0) || (evt != null ? evt.target.nodeName.toLowerCase() : void 0) === 'input') {
1051
+ return;
1052
+ }
1053
+ return openScope.$apply(function() {
1054
+ return openScope.isOpen = false;
1055
+ });
1056
+ };
1057
+ escapeKeyBind = function(evt) {
1058
+ if (evt.which === 27) {
1059
+ openScope.focusToggleElement();
1060
+ return closeDropdown();
1061
+ }
1062
+ };
1063
+ return this;
1064
+ }
1065
+ ]).controller('DropdownController', [
1066
+ '$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {
1067
+ var dropDownOpen, getIsOpen, scope, self, setIsOpen, toggleInvoker;
1068
+ self = this;
1069
+ scope = $scope.$new();
1070
+ dropDownOpen = dropdownConfig.dropDownOpen;
1071
+ getIsOpen = void 0;
1072
+ setIsOpen = angular.noop;
1073
+ toggleInvoker = ($attrs.onToggle ? $parse($attrs.onToggle) : angular.noop);
1074
+ this.init = function(element) {
1075
+ self.$element = element;
1076
+ if ($attrs.isOpen) {
1077
+ getIsOpen = $parse($attrs.isOpen);
1078
+ setIsOpen = getIsOpen.assign;
1079
+ return $scope.$watch(getIsOpen, function(value) {
1080
+ return scope.isOpen = !!value;
1081
+ });
1082
+ }
1083
+ };
1084
+ this.toggle = function(open) {
1085
+ return scope.isOpen = (arguments.length ? !!open : !scope.isOpen);
1086
+ };
1087
+ this.isOpen = function() {
1088
+ return scope.isOpen;
1089
+ };
1090
+ scope.getToggleElement = function() {
1091
+ return self.toggleElement;
1092
+ };
1093
+ scope.focusToggleElement = function() {
1094
+ if (self.toggleElement) {
1095
+ self.toggleElement[0].focus();
1096
+ }
1097
+ };
1098
+ scope.$watch('isOpen', function(isOpen, wasOpen) {
1099
+ var anchors;
1100
+ anchors = self.$element.find('a');
1101
+ if (isOpen) {
1102
+ self.$element.attr(dropDownOpen, '');
1103
+ scope.focusToggleElement();
1104
+ dropdownService.open(scope);
1105
+ if (anchors.length) {
1106
+ scope.forceClose = true;
1107
+ _.each(anchors, function(anchor) {
1108
+ return angular.element(anchor).on('click', function(evt) {
1109
+ dropdownService.close(scope);
1110
+ return scope.$digest();
1111
+ });
1112
+ });
1113
+ }
1114
+ } else {
1115
+ self.$element.removeAttr(dropDownOpen);
1116
+ dropdownService.close(scope);
1117
+ }
1118
+ setIsOpen($scope, isOpen);
1119
+ if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
1120
+ return toggleInvoker($scope, {
1121
+ open: !!isOpen
1122
+ });
1123
+ }
1124
+ });
1125
+ $scope.$on('$locationChangeSuccess', function() {
1126
+ return scope.isOpen = false;
1127
+ });
1128
+ $scope.$on('$destroy', function() {
1129
+ return scope.$destroy();
1130
+ });
1131
+ return this;
1132
+ }
1133
+ ]).directive('dropdown', function() {
1134
+ return {
1135
+ controller: 'DropdownController',
1136
+ link: function(scope, element, attrs, dropdownCtrl) {
1137
+ return dropdownCtrl.init(element);
1138
+ }
1139
+ };
1140
+ }).directive('dropdownToggle', function() {
1141
+ return {
1142
+ require: '?^dropdown',
1143
+ link: function(scope, element, attrs, dropdownCtrl) {
1144
+ var toggleDropdown;
1145
+ if (!dropdownCtrl) {
1146
+ return;
1147
+ }
1148
+ dropdownCtrl.toggleElement = element;
1149
+ toggleDropdown = function(event) {
1150
+ event.preventDefault();
1151
+ if (!element.hasClass('disabled') && !attrs.disabled) {
1152
+ return scope.$apply(function() {
1153
+ return dropdownCtrl.toggle();
1154
+ });
1155
+ }
1156
+ };
1157
+ element.bind('click', toggleDropdown);
1158
+ element.attr({
1159
+ 'aria-haspopup': true,
1160
+ 'aria-expanded': false
1161
+ });
1162
+ scope.$watch(dropdownCtrl.isOpen, function(isOpen) {
1163
+ return element.attr('aria-expanded', !!isOpen);
1164
+ });
1165
+ return scope.$on('$destroy', function() {
1166
+ return element.unbind('click', toggleDropdown);
1167
+ });
1168
+ }
1169
+ };
1170
+ });
1171
+
1172
+ }).call(this);
1173
+
1174
+ (function() {
1175
+ angular.module("rolodex.modal", ["rolodex.transition", "templates"]).factory("$$stackedMap", function() {
1176
+ return {
1177
+ createNew: function() {
1178
+ var stack;
1179
+ stack = [];
1180
+ return {
1181
+ add: function(key, value) {
1182
+ return stack.push({
1183
+ key: key,
1184
+ value: value
1185
+ });
1186
+ },
1187
+ get: function(key) {
1188
+ var i;
1189
+ i = 0;
1190
+ while (i < stack.length) {
1191
+ if (key === stack[i].key) {
1192
+ return stack[i];
1193
+ }
1194
+ i++;
1195
+ }
1196
+ },
1197
+ keys: function() {
1198
+ var i, keys;
1199
+ keys = [];
1200
+ i = 0;
1201
+ while (i < stack.length) {
1202
+ keys.push(stack[i].key);
1203
+ i++;
1204
+ }
1205
+ return keys;
1206
+ },
1207
+ top: function() {
1208
+ return stack[stack.length - 1];
1209
+ },
1210
+ remove: function(key) {
1211
+ var i, idx;
1212
+ idx = -1;
1213
+ i = 0;
1214
+ while (i < stack.length) {
1215
+ if (key === stack[i].key) {
1216
+ idx = i;
1217
+ break;
1218
+ }
1219
+ i++;
1220
+ }
1221
+ return stack.splice(idx, 1)[0];
1222
+ },
1223
+ removeTop: function() {
1224
+ return stack.splice(stack.length - 1, 1)[0];
1225
+ },
1226
+ length: function() {
1227
+ return stack.length;
1228
+ }
1229
+ };
1230
+ }
1231
+ };
1232
+ }).directive("modalWindow", [
1233
+ "$modalStack", "$timeout", function($modalStack, $timeout) {
1234
+ return {
1235
+ restrict: "EA",
1236
+ scope: {
1237
+ index: "@",
1238
+ animate: "="
1239
+ },
1240
+ replace: true,
1241
+ transclude: true,
1242
+ templateUrl: function(tElement, tAttrs) {
1243
+ return tAttrs.templateUrl || "rolodex_angular/template/modal/window";
1244
+ },
1245
+ link: function(scope, element, attrs) {
1246
+ element.addClass(attrs.windowClass || "");
1247
+ scope.size = attrs.size;
1248
+ $timeout(function() {
1249
+ scope.animate = true;
1250
+ if (!element[0].querySelectorAll("[autofocus]").length) {
1251
+ element[0].focus();
1252
+ }
1253
+ });
1254
+ return scope.close = function(evt) {
1255
+ var modal;
1256
+ modal = $modalStack.getTop();
1257
+ if (modal && modal.value.backdrop && modal.value.backdrop !== "static" && (evt.target === evt.currentTarget)) {
1258
+ evt.preventDefault();
1259
+ evt.stopPropagation();
1260
+ return $modalStack.dismiss(modal.key, "backdrop click");
1261
+ }
1262
+ };
1263
+ }
1264
+ };
1265
+ }
1266
+ ]).directive("modalTransclude", function() {
1267
+ return {
1268
+ link: function($scope, $element, $attrs, controller, $transclude) {
1269
+ return $transclude($scope.$parent, function(clone) {
1270
+ $element.empty();
1271
+ return $element.append(clone);
1272
+ });
1273
+ }
1274
+ };
1275
+ }).factory("$modalStack", [
1276
+ "$transition", "$timeout", "$document", "$compile", "$rootScope", "$$stackedMap", function($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
1277
+ var $modalStack, OPENED_MODAL_CLASS, backdropDomEl, backdropIndex, backdropScope, checkRemoveBackdrop, openedWindows, removeAfterAnimate, removeModalWindow;
1278
+ backdropIndex = function() {
1279
+ var i, opened, topBackdropIndex;
1280
+ topBackdropIndex = -1;
1281
+ opened = openedWindows.keys();
1282
+ i = 0;
1283
+ while (i < opened.length) {
1284
+ if (openedWindows.get(opened[i]).value.backdrop) {
1285
+ topBackdropIndex = i;
1286
+ }
1287
+ i++;
1288
+ }
1289
+ return topBackdropIndex;
1290
+ };
1291
+ removeModalWindow = function(modalInstance) {
1292
+ var body, modalWindow;
1293
+ body = $document.find("body").eq(0);
1294
+ modalWindow = openedWindows.get(modalInstance).value;
1295
+ openedWindows.remove(modalInstance);
1296
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {
1297
+ modalWindow.modalScope.$destroy();
1298
+ body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1299
+ checkRemoveBackdrop();
1300
+ });
1301
+ };
1302
+ checkRemoveBackdrop = function() {
1303
+ var backdropDomEl, backdropScope, backdropScopeRef;
1304
+ if (backdropDomEl && backdropIndex() === -1) {
1305
+ backdropScopeRef = backdropScope;
1306
+ removeAfterAnimate(backdropDomEl, backdropScope, 150, function() {
1307
+ backdropScopeRef.$destroy();
1308
+ backdropScopeRef = null;
1309
+ });
1310
+ backdropDomEl = undefined;
1311
+ backdropScope = undefined;
1312
+ }
1313
+ };
1314
+ removeAfterAnimate = function(domEl, scope, emulateTime, done) {
1315
+ var afterAnimating, timeout, transitionEndEventName;
1316
+ afterAnimating = function() {
1317
+ if (afterAnimating.done) {
1318
+ return;
1319
+ }
1320
+ afterAnimating.done = true;
1321
+ domEl.remove();
1322
+ if (done) {
1323
+ done();
1324
+ }
1325
+ };
1326
+ scope.animate = false;
1327
+ transitionEndEventName = $transition.transitionEndEventName;
1328
+ if (transitionEndEventName) {
1329
+ timeout = $timeout(afterAnimating, emulateTime);
1330
+ domEl.bind(transitionEndEventName, function() {
1331
+ $timeout.cancel(timeout);
1332
+ afterAnimating();
1333
+ scope.$apply();
1334
+ });
1335
+ } else {
1336
+ $timeout(afterAnimating);
1337
+ }
1338
+ };
1339
+ OPENED_MODAL_CLASS = "modal-open";
1340
+ backdropDomEl = void 0;
1341
+ backdropScope = void 0;
1342
+ openedWindows = $$stackedMap.createNew();
1343
+ $modalStack = {};
1344
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
1345
+ if (backdropScope) {
1346
+ backdropScope.index = newBackdropIndex;
1347
+ }
1348
+ });
1349
+ $document.bind("keydown", function(evt) {
1350
+ var modal;
1351
+ modal = void 0;
1352
+ if (evt.which === 27) {
1353
+ modal = openedWindows.top();
1354
+ if (modal && modal.value.keyboard) {
1355
+ evt.preventDefault();
1356
+ $rootScope.$apply(function() {
1357
+ $modalStack.dismiss(modal.key, "escape key press");
1358
+ });
1359
+ }
1360
+ }
1361
+ });
1362
+ $modalStack.open = function(modalInstance, modal) {
1363
+ var angularBackgroundDomEl, angularDomEl, body, currBackdropIndex, modalDomEl;
1364
+ openedWindows.add(modalInstance, {
1365
+ deferred: modal.deferred,
1366
+ modalScope: modal.scope,
1367
+ backdrop: modal.backdrop,
1368
+ keyboard: modal.keyboard
1369
+ });
1370
+ body = $document.find("body").eq(0);
1371
+ currBackdropIndex = backdropIndex();
1372
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
1373
+ backdropScope = $rootScope.$new(true);
1374
+ backdropScope.index = currBackdropIndex;
1375
+ angularBackgroundDomEl = angular.element("<div modal-backdrop></div>");
1376
+ angularBackgroundDomEl.attr("backdrop-class", modal.backdropClass);
1377
+ backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
1378
+ body.append(backdropDomEl);
1379
+ }
1380
+ angularDomEl = angular.element("<div modal-window></div>");
1381
+ angularDomEl.attr({
1382
+ "template-url": modal.windowTemplateUrl,
1383
+ "window-class": modal.windowClass,
1384
+ size: modal.size,
1385
+ index: openedWindows.length() - 1,
1386
+ animate: "animate"
1387
+ }).html(modal.content);
1388
+ modalDomEl = $compile(angularDomEl)(modal.scope);
1389
+ openedWindows.top().value.modalDomEl = modalDomEl;
1390
+ body.append(modalDomEl);
1391
+ body.addClass(OPENED_MODAL_CLASS);
1392
+ };
1393
+ $modalStack.close = function(modalInstance, result) {
1394
+ var modalWindow;
1395
+ modalWindow = openedWindows.get(modalInstance);
1396
+ if (modalWindow) {
1397
+ modalWindow.value.deferred.resolve(result);
1398
+ removeModalWindow(modalInstance);
1399
+ }
1400
+ };
1401
+ $modalStack.dismiss = function(modalInstance, reason) {
1402
+ var modalWindow;
1403
+ modalWindow = openedWindows.get(modalInstance);
1404
+ if (modalWindow) {
1405
+ modalWindow.value.deferred.reject(reason);
1406
+ removeModalWindow(modalInstance);
1407
+ }
1408
+ };
1409
+ $modalStack.dismissAll = function(reason) {
1410
+ var topModal;
1411
+ topModal = this.getTop();
1412
+ while (topModal) {
1413
+ this.dismiss(topModal.key, reason);
1414
+ topModal = this.getTop();
1415
+ }
1416
+ };
1417
+ $modalStack.getTop = function() {
1418
+ return openedWindows.top();
1419
+ };
1420
+ return $modalStack;
1421
+ }
1422
+ ]).provider("$modal", function() {
1423
+ var $modalProvider;
1424
+ $modalProvider = {
1425
+ options: {
1426
+ backdrop: true,
1427
+ keyboard: true
1428
+ },
1429
+ $get: [
1430
+ "$injector", "$rootScope", "$q", "$http", "$templateCache", "$controller", "$modalStack", function($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
1431
+ var $modal, getResolvePromises, getTemplatePromise;
1432
+ getTemplatePromise = function(options) {
1433
+ if (options.template) {
1434
+ return $q.when(options.template);
1435
+ } else {
1436
+ return $http.get((angular.isFunction(options.templateUrl) ? options.templateUrl() : options.templateUrl), {
1437
+ cache: $templateCache
1438
+ }).then(function(result) {
1439
+ return result.data;
1440
+ });
1441
+ }
1442
+ };
1443
+ getResolvePromises = function(resolves) {
1444
+ var promisesArr;
1445
+ promisesArr = [];
1446
+ angular.forEach(resolves, function(value) {
1447
+ if (angular.isFunction(value) || angular.isArray(value)) {
1448
+ promisesArr.push($q.when($injector.invoke(value)));
1449
+ }
1450
+ });
1451
+ return promisesArr;
1452
+ };
1453
+ $modal = {};
1454
+ $modal.open = function(modalOptions) {
1455
+ var modalInstance, modalOpenedDeferred, modalResultDeferred, resolveError, resolveSuccess, templateAndResolvePromise;
1456
+ modalResultDeferred = $q.defer();
1457
+ modalOpenedDeferred = $q.defer();
1458
+ modalInstance = {
1459
+ result: modalResultDeferred.promise,
1460
+ opened: modalOpenedDeferred.promise,
1461
+ close: function(result) {
1462
+ $modalStack.close(modalInstance, result);
1463
+ },
1464
+ dismiss: function(reason) {
1465
+ $modalStack.dismiss(modalInstance, reason);
1466
+ }
1467
+ };
1468
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
1469
+ modalOptions.resolve = modalOptions.resolve || {};
1470
+ if (!modalOptions.template && !modalOptions.templateUrl) {
1471
+ throw new Error("One of template or templateUrl options is required.");
1472
+ }
1473
+ templateAndResolvePromise = $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
1474
+ templateAndResolvePromise.then((resolveSuccess = function(tplAndVars) {
1475
+ var ctrlInstance, ctrlLocals, modalScope, resolveIter;
1476
+ modalScope = (modalOptions.scope || $rootScope).$new();
1477
+ modalScope.$close = modalInstance.close;
1478
+ modalScope.$dismiss = modalInstance.dismiss;
1479
+ ctrlInstance = void 0;
1480
+ ctrlLocals = {};
1481
+ resolveIter = 1;
1482
+ if (modalOptions.controller) {
1483
+ ctrlLocals.$scope = modalScope;
1484
+ ctrlLocals.$modalInstance = modalInstance;
1485
+ angular.forEach(modalOptions.resolve, function(value, key) {
1486
+ ctrlLocals[key] = tplAndVars[resolveIter++];
1487
+ });
1488
+ ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
1489
+ if (modalOptions.controller) {
1490
+ modalScope[modalOptions.controllerAs] = ctrlInstance;
1491
+ }
1492
+ }
1493
+ return $modalStack.open(modalInstance, {
1494
+ scope: modalScope,
1495
+ deferred: modalResultDeferred,
1496
+ content: tplAndVars[0],
1497
+ backdrop: modalOptions.backdrop,
1498
+ keyboard: modalOptions.keyboard,
1499
+ backdropClass: modalOptions.backdropClass,
1500
+ windowClass: modalOptions.windowClass,
1501
+ windowTemplateUrl: modalOptions.windowTemplateUrl,
1502
+ size: modalOptions.size
1503
+ });
1504
+ }), resolveError = function(reason) {
1505
+ return modalResultDeferred.reject(reason);
1506
+ });
1507
+ templateAndResolvePromise.then((function() {
1508
+ return modalOpenedDeferred.resolve(true);
1509
+ }), function() {
1510
+ return modalOpenedDeferred.reject(false);
1511
+ });
1512
+ return modalInstance;
1513
+ };
1514
+ return $modal;
1515
+ }
1516
+ ]
1517
+ };
1518
+ return $modalProvider;
1519
+ });
1520
+
1521
+ }).call(this);
1522
+
1523
+
1524
+ /**
1525
+ A set of utility methods that can be use to retrieve position of DOM elements.
1526
+ It is meant to be used where we need to absolute-position DOM elements in
1527
+ relation to other, existing elements (this is the case for tooltips, popovers,
1528
+ typeahead suggestions etc.).
1529
+ */
1530
+
1531
+ (function() {
1532
+ angular.module('rolodex.position', []).factory('$position', [
1533
+ '$document', '$window', function($document, $window) {
1534
+ var getStyle, isStaticPositioned, parentOffsetEl;
1535
+ getStyle = function(el, cssprop) {
1536
+ if (el.currentStyle) {
1537
+ return el.currentStyle[cssprop];
1538
+ } else {
1539
+ if ($window.getComputedStyle) {
1540
+ return $window.getComputedStyle(el)[cssprop];
1541
+ }
1542
+ }
1543
+ return el.style[cssprop];
1544
+ };
1545
+
1546
+ /**
1547
+ Checks if a given element is statically positioned
1548
+ @param element - raw DOM element
1549
+ */
1550
+ isStaticPositioned = function(element) {
1551
+ return (getStyle(element, 'position') || 'static') === 'static';
1552
+ };
1553
+
1554
+ /**
1555
+ returns the closest, non-statically positioned parentOffset of a given element
1556
+ @param element
1557
+ */
1558
+ parentOffsetEl = function(element) {
1559
+ var docDomEl, offsetParent;
1560
+ docDomEl = $document[0];
1561
+ offsetParent = element.offsetParent || docDomEl;
1562
+ while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
1563
+ offsetParent = offsetParent.offsetParent;
1564
+ }
1565
+ return offsetParent || docDomEl;
1566
+ };
1567
+ return {
1568
+
1569
+ /**
1570
+ Provides read-only equivalent of jQuery's position function:
1571
+ http://api.jquery.com/position/
1572
+ */
1573
+ position: function(element) {
1574
+ var boundingClientRect, elBCR, offsetParentBCR, offsetParentEl;
1575
+ elBCR = this.offset(element);
1576
+ offsetParentBCR = {
1577
+ top: 0,
1578
+ left: 0
1579
+ };
1580
+ offsetParentEl = parentOffsetEl(element[0]);
1581
+ if (offsetParentEl !== $document[0]) {
1582
+ offsetParentBCR = this.offset(angular.element(offsetParentEl));
1583
+ offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
1584
+ offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
1585
+ }
1586
+ boundingClientRect = element[0].getBoundingClientRect();
1587
+ return {
1588
+ width: boundingClientRect.width || element.prop('offsetWidth'),
1589
+ height: boundingClientRect.height || element.prop('offsetHeight'),
1590
+ top: elBCR.top - offsetParentBCR.top,
1591
+ left: elBCR.left - offsetParentBCR.left
1592
+ };
1593
+ },
1594
+
1595
+ /**
1596
+ Provides read-only equivalent of jQuery's offset function:
1597
+ http://api.jquery.com/offset/
1598
+ */
1599
+ offset: function(element) {
1600
+ var boundingClientRect;
1601
+ boundingClientRect = element[0].getBoundingClientRect();
1602
+ return {
1603
+ width: boundingClientRect.width || element.prop('offsetWidth'),
1604
+ height: boundingClientRect.height || element.prop('offsetHeight'),
1605
+ top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
1606
+ left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
1607
+ };
1608
+ },
1609
+
1610
+ /**
1611
+ Provides coordinates for the targetEl in relation to hostEl
1612
+ */
1613
+ positionElements: function(hostEl, targetEl, positionStr, appendToBody) {
1614
+ var hostElPos, pos0, pos1, positionStrParts, shiftHeight, shiftWidth, targetElHeight, targetElPos, targetElWidth;
1615
+ positionStrParts = positionStr.split('-');
1616
+ pos0 = positionStrParts[0];
1617
+ pos1 = positionStrParts[1] || 'center';
1618
+ hostElPos = void 0;
1619
+ targetElWidth = void 0;
1620
+ targetElHeight = void 0;
1621
+ targetElPos = void 0;
1622
+ hostElPos = (appendToBody ? this.offset(hostEl) : this.position(hostEl));
1623
+ targetElWidth = targetEl.prop('offsetWidth');
1624
+ targetElHeight = targetEl.prop('offsetHeight');
1625
+ shiftWidth = {
1626
+ center: function() {
1627
+ return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
1628
+ },
1629
+ left: function() {
1630
+ return hostElPos.left;
1631
+ },
1632
+ right: function() {
1633
+ return hostElPos.left + hostElPos.width;
1634
+ }
1635
+ };
1636
+ shiftHeight = {
1637
+ center: function() {
1638
+ return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
1639
+ },
1640
+ top: function() {
1641
+ return hostElPos.top;
1642
+ },
1643
+ bottom: function() {
1644
+ return hostElPos.top + hostElPos.height;
1645
+ }
1646
+ };
1647
+ switch (pos0) {
1648
+ case 'right':
1649
+ targetElPos = {
1650
+ top: shiftHeight[pos1](),
1651
+ left: shiftWidth[pos0]()
1652
+ };
1653
+ break;
1654
+ case 'left':
1655
+ targetElPos = {
1656
+ top: shiftHeight[pos1](),
1657
+ left: hostElPos.left - targetElWidth
1658
+ };
1659
+ break;
1660
+ case 'bottom':
1661
+ targetElPos = {
1662
+ top: shiftHeight[pos0](),
1663
+ left: shiftWidth[pos1]()
1664
+ };
1665
+ break;
1666
+ default:
1667
+ targetElPos = {
1668
+ top: hostElPos.top - targetElHeight,
1669
+ left: shiftWidth[pos1]()
1670
+ };
1671
+ }
1672
+ return targetElPos;
1673
+ }
1674
+ };
1675
+ }
1676
+ ]);
1677
+
1678
+ }).call(this);
1679
+
1680
+ (function() {
1681
+ angular.module("rolodex.transition", []).factory("$transition", [
1682
+ "$q", "$timeout", "$rootScope", function($q, $timeout, $rootScope) {
1683
+ var $transition, animationEndEventNames, findEndEventName, transElement, transitionEndEventNames;
1684
+ findEndEventName = function(endEventNames) {
1685
+ var name;
1686
+ for (name in endEventNames) {
1687
+ if (transElement.style[name] !== undefined) {
1688
+ return endEventNames[name];
1689
+ }
1690
+ }
1691
+ };
1692
+ $transition = function(element, trigger, options) {
1693
+ var deferred, endEventName, transitionEndHandler;
1694
+ options = options || {};
1695
+ deferred = $q.defer();
1696
+ endEventName = $transition[(options.animation ? "animationEndEventName" : "transitionEndEventName")];
1697
+ transitionEndHandler = function(event) {
1698
+ $rootScope.$apply(function() {
1699
+ element.unbind(endEventName, transitionEndHandler);
1700
+ deferred.resolve(element);
1701
+ });
1702
+ };
1703
+ if (endEventName) {
1704
+ element.bind(endEventName, transitionEndHandler);
1705
+ }
1706
+ $timeout(function() {
1707
+ if (angular.isString(trigger)) {
1708
+ element.addClass(trigger);
1709
+ } else if (angular.isFunction(trigger)) {
1710
+ trigger(element);
1711
+ } else {
1712
+ if (angular.isObject(trigger)) {
1713
+ element.css(trigger);
1714
+ }
1715
+ }
1716
+ if (!endEventName) {
1717
+ deferred.resolve(element);
1718
+ }
1719
+ });
1720
+ deferred.promise.cancel = function() {
1721
+ if (endEventName) {
1722
+ element.unbind(endEventName, transitionEndHandler);
1723
+ }
1724
+ deferred.reject("Transition cancelled");
1725
+ };
1726
+ return deferred.promise;
1727
+ };
1728
+ transElement = document.createElement("trans");
1729
+ transitionEndEventNames = {
1730
+ WebkitTransition: "webkitTransitionEnd",
1731
+ MozTransition: "transitionend",
1732
+ OTransition: "oTransitionEnd",
1733
+ transition: "transitionend"
1734
+ };
1735
+ animationEndEventNames = {
1736
+ WebkitTransition: "webkitAnimationEnd",
1737
+ MozTransition: "animationend",
1738
+ OTransition: "oAnimationEnd",
1739
+ transition: "animationend"
1740
+ };
1741
+ $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
1742
+ $transition.animationEndEventName = findEndEventName(animationEndEventNames);
1743
+ return $transition;
1744
+ }
1745
+ ]);
1746
+
1747
+ }).call(this);