rolodex 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +1 -0
- data/karma.conf.js +87 -0
- data/lib/rolodex.rb +31 -0
- data/lib/rolodex/engine.rb +12 -0
- data/lib/rolodex/sass.rb +5 -0
- data/lib/rolodex/version.rb +3 -0
- data/package.json +33 -0
- data/rolodex.gemspec +29 -0
- data/spec/javascripts/rolodex_angular/modal.spec.coffee +13 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/test_lib/angular-mocks.js +2173 -0
- data/spec/test_lib/angular.js +21883 -0
- data/spec/test_lib/jquery-2.1.1.js +9190 -0
- data/spec/test_lib/lodash.js +6785 -0
- data/vendor/assets/.keep +0 -0
- data/vendor/assets/images/alerts/icon-danger-dark.png +0 -0
- data/vendor/assets/images/alerts/icon-danger-dark.svg +9 -0
- data/vendor/assets/images/alerts/icon-danger-light.png +0 -0
- data/vendor/assets/images/alerts/icon-danger-light.svg +9 -0
- data/vendor/assets/images/alerts/icon-flop-dark.png +0 -0
- data/vendor/assets/images/alerts/icon-flop-dark.svg +11 -0
- data/vendor/assets/images/alerts/icon-flop-light.png +0 -0
- data/vendor/assets/images/alerts/icon-flop-light.svg +11 -0
- data/vendor/assets/images/alerts/icon-info-dark.png +0 -0
- data/vendor/assets/images/alerts/icon-info-dark.svg +9 -0
- data/vendor/assets/images/alerts/icon-info-light.png +0 -0
- data/vendor/assets/images/alerts/icon-info-light.svg +9 -0
- data/vendor/assets/images/alerts/icon-tick-dark.png +0 -0
- data/vendor/assets/images/alerts/icon-tick-dark.svg +9 -0
- data/vendor/assets/images/alerts/icon-tick-light.png +0 -0
- data/vendor/assets/images/alerts/icon-tick-light.svg +9 -0
- data/vendor/assets/images/forms/checkbox.png +0 -0
- data/vendor/assets/images/forms/checkbox.svg +13 -0
- data/vendor/assets/images/forms/icon-calendar.png +0 -0
- data/vendor/assets/images/forms/icon-calendar.svg +20 -0
- data/vendor/assets/images/forms/icon-search.png +0 -0
- data/vendor/assets/images/forms/icon-search.svg +13 -0
- data/vendor/assets/images/forms/icon-validating.gif +0 -0
- data/vendor/assets/images/forms/icon-validating.psd +0 -0
- data/vendor/assets/images/forms/radio-button.png +0 -0
- data/vendor/assets/images/forms/radio-button.svg +12 -0
- data/vendor/assets/images/icons/icon-caret.png +0 -0
- data/vendor/assets/images/icons/icon-caret.svg +24 -0
- data/vendor/assets/images/icons/icon-close-x.png +0 -0
- data/vendor/assets/images/icons/icon-close-x.svg +9 -0
- data/vendor/assets/images/icons/icon-expand-gray.png +0 -0
- data/vendor/assets/images/icons/icon-expand-gray.svg +11 -0
- data/vendor/assets/images/icons/icon-expand-white.png +0 -0
- data/vendor/assets/images/icons/icon-expand-white.svg +11 -0
- data/vendor/assets/images/icons/icon-image.png +0 -0
- data/vendor/assets/images/icons/icon-image.svg +12 -0
- data/vendor/assets/images/icons/icon-invalid.png +0 -0
- data/vendor/assets/images/icons/icon-invalid.svg +14 -0
- data/vendor/assets/images/icons/icon-plane.png +0 -0
- data/vendor/assets/images/icons/icon-plane.svg +15 -0
- data/vendor/assets/images/icons/icon-star-banner.png +0 -0
- data/vendor/assets/images/icons/icon-star-banner.svg +16 -0
- data/vendor/assets/images/icons/icon-suggest.png +0 -0
- data/vendor/assets/images/icons/icon-suggest.svg +15 -0
- data/vendor/assets/images/icons/icon-tick.png +0 -0
- data/vendor/assets/images/icons/icon-tick.svg +9 -0
- data/vendor/assets/images/icons/icon-valid.png +0 -0
- data/vendor/assets/images/icons/icon-valid.svg +9 -0
- data/vendor/assets/images/loading/loading.png +0 -0
- data/vendor/assets/images/loading/loading.svg +23 -0
- data/vendor/assets/images/logo/belly-logo.png +0 -0
- data/vendor/assets/images/logo/belly-logo.svg +19 -0
- data/vendor/assets/images/tooltips/tooltip-star.png +0 -0
- data/vendor/assets/images/tooltips/tooltip-star.svg +20 -0
- data/vendor/assets/javascripts/rolodex_angular.coffee +3 -0
- data/vendor/assets/javascripts/rolodex_angular/README.md +68 -0
- data/vendor/assets/javascripts/rolodex_angular/rolodex.coffee +11 -0
- data/vendor/assets/javascripts/rolodex_angular/src/accordion.coffee +100 -0
- data/vendor/assets/javascripts/rolodex_angular/src/alert.coffee +17 -0
- data/vendor/assets/javascripts/rolodex_angular/src/buttons.coffee +59 -0
- data/vendor/assets/javascripts/rolodex_angular/src/collapse.coffee +65 -0
- data/vendor/assets/javascripts/rolodex_angular/src/dateparser.coffee +125 -0
- data/vendor/assets/javascripts/rolodex_angular/src/datepicker.coffee +547 -0
- data/vendor/assets/javascripts/rolodex_angular/src/dropdown.coffee +143 -0
- data/vendor/assets/javascripts/rolodex_angular/src/modal.coffee +331 -0
- data/vendor/assets/javascripts/rolodex_angular/src/position.coffee +128 -0
- data/vendor/assets/javascripts/rolodex_angular/src/transition.coffee +73 -0
- data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion-group.ngt.haml +7 -0
- data/vendor/assets/javascripts/rolodex_angular/template/accordion/accordion.ngt.haml +1 -0
- data/vendor/assets/javascripts/rolodex_angular/template/alert/alert.ngt.haml +3 -0
- data/vendor/assets/javascripts/rolodex_angular/template/datepicker/datepicker.ngt.haml +4 -0
- data/vendor/assets/javascripts/rolodex_angular/template/datepicker/day.ngt.haml +20 -0
- data/vendor/assets/javascripts/rolodex_angular/template/datepicker/month.ngt.haml +17 -0
- data/vendor/assets/javascripts/rolodex_angular/template/datepicker/popup.ngt.haml +2 -0
- data/vendor/assets/javascripts/rolodex_angular/template/datepicker/year.ngt.haml +17 -0
- data/vendor/assets/javascripts/rolodex_angular/template/modal/window.ngt.haml +2 -0
- data/vendor/assets/javascripts/vendor/jquery-1.10.2.min.js +6 -0
- data/vendor/assets/javascripts/vendor/modernizr-2.6.2.min.js +4 -0
- data/vendor/assets/stylesheets/rolodex.css.sass +26 -0
- data/vendor/assets/stylesheets/rolodex/base/_layout.sass +58 -0
- data/vendor/assets/stylesheets/rolodex/base/_typography.sass +123 -0
- data/vendor/assets/stylesheets/rolodex/components/_alerts.sass +112 -0
- data/vendor/assets/stylesheets/rolodex/components/_buttons.sass +103 -0
- data/vendor/assets/stylesheets/rolodex/components/_dropdowns.sass +121 -0
- data/vendor/assets/stylesheets/rolodex/components/_forms.sass +326 -0
- data/vendor/assets/stylesheets/rolodex/components/_icons.sass +76 -0
- data/vendor/assets/stylesheets/rolodex/components/_labels.sass +29 -0
- data/vendor/assets/stylesheets/rolodex/components/_lists.sass +15 -0
- data/vendor/assets/stylesheets/rolodex/components/_loading.sass +32 -0
- data/vendor/assets/stylesheets/rolodex/components/_media.sass +14 -0
- data/vendor/assets/stylesheets/rolodex/components/_modals.sass +83 -0
- data/vendor/assets/stylesheets/rolodex/components/_tables.sass +9 -0
- data/vendor/assets/stylesheets/rolodex/components/_tooltips.sass +123 -0
- data/vendor/assets/stylesheets/rolodex/settings/_settings.sass +33 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_bump.sass +51 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_icons.sass +17 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_layout.sass +52 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_rems.sass +41 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_svg.sass +10 -0
- data/vendor/assets/stylesheets/rolodex/settings/mixins/_typography.sass +65 -0
- data/vendor/assets/stylesheets/rolodex/settings/utilities/_layout.sass +51 -0
- data/vendor/assets/stylesheets/rolodex/settings/utilities/_misc.sass +13 -0
- data/vendor/assets/stylesheets/rolodex/settings/utilities/_typography.sass +60 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_alerts.scss +27 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_buttons.scss +10 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_colors.scss +46 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_labels.scss +10 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_layout.scss +22 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_misc.scss +12 -0
- data/vendor/assets/stylesheets/rolodex/settings/variables/_typography.scss +34 -0
- metadata +263 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
# [Angular](https://angularjs.org/) modules just for [Rolodex](https://github.com/bellycard/rolodex)
|
2
|
+
|
3
|
+
***
|
4
|
+
|
5
|
+
## Wat?
|
6
|
+
Rolodex components written in Angular. Rolodex Angular has very few dependencies, requiring only [AngularJS](https://angularjs.org/), of course, and [LoDash](http://lodash.com/) (or [Underscore](http://underscorejs.org/)). The collection of directives should be very simple to use, fast, and drop in seamlessly when using Rolodex styles and classes. jQuery is not required for any of these modules to work now and forever. This project is heavily infulenced by [UI Bootstrap](http://angular-ui.github.io/bootstrap/).
|
7
|
+
|
8
|
+
## See Rolodex Angular In Action
|
9
|
+
[Belly Style Guide](https://style.bellycard.com/)
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
Required libraries
|
13
|
+
|
14
|
+
* [AngularJS](https://angularjs.org/)
|
15
|
+
* [LoDash](http://lodash.com/) or [Underscore](http://underscorejs.org/)
|
16
|
+
|
17
|
+
Make sure that both are loaded before Rolodex.
|
18
|
+
|
19
|
+
Add to your `Gemfile:`
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'rolodex', :git => 'https://github.com/bellycard/rolodex.git'
|
23
|
+
```
|
24
|
+
|
25
|
+
Import to your main coffee/js file
|
26
|
+
|
27
|
+
```coffeescript
|
28
|
+
#= require 'rolodex_angular'
|
29
|
+
```
|
30
|
+
|
31
|
+
Add Rolodex to your Angular App
|
32
|
+
|
33
|
+
```coffeescript
|
34
|
+
angular.module('myApp', ['rolodex'])
|
35
|
+
```
|
36
|
+
|
37
|
+
## Dial Up Only What You Need
|
38
|
+
Utilizing Angular's flexible module system each directive is its own module which means you don't have to import then entire rolodex module if you don't need it. No need for jQuery either - each module should be independent of jQuery. Guaranteed. Forever.
|
39
|
+
|
40
|
+
## Tested Browsers
|
41
|
+
* Chrome
|
42
|
+
* Safari
|
43
|
+
* IE 9/10
|
44
|
+
* Opera
|
45
|
+
|
46
|
+
## Development
|
47
|
+
You will need already installed:
|
48
|
+
|
49
|
+
* Ruby
|
50
|
+
* NodeJS (For Karma, the test runner)
|
51
|
+
|
52
|
+
Run Bundler
|
53
|
+
|
54
|
+
```
|
55
|
+
$: bundle install
|
56
|
+
```
|
57
|
+
|
58
|
+
Run NPM install
|
59
|
+
|
60
|
+
```
|
61
|
+
$: npm install
|
62
|
+
```
|
63
|
+
|
64
|
+
Run Karma
|
65
|
+
|
66
|
+
```
|
67
|
+
$: npm test_angular
|
68
|
+
```
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#= require 'rolodex_angular/template/accordion/accordion'
|
2
|
+
#= require 'rolodex_angular/template/accordion/accordion-group'
|
3
|
+
|
4
|
+
angular.module("rolodex.accordion", ["rolodex.collapse"])
|
5
|
+
|
6
|
+
.constant("accordionConfig", closeOthers: true)
|
7
|
+
|
8
|
+
.controller("AccordionController", [
|
9
|
+
"$scope"
|
10
|
+
"$attrs"
|
11
|
+
"accordionConfig"
|
12
|
+
($scope, $attrs, accordionConfig) ->
|
13
|
+
# This array keeps track of the accordion groups
|
14
|
+
@groups = []
|
15
|
+
|
16
|
+
# Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
|
17
|
+
@closeOthers = (openGroup) ->
|
18
|
+
closeOthers = (if angular.isDefined($attrs.closeOthers) then $scope.$eval($attrs.closeOthers) else accordionConfig.closeOthers)
|
19
|
+
if closeOthers
|
20
|
+
angular.forEach @groups, (group) ->
|
21
|
+
group.isOpen = false if group isnt openGroup
|
22
|
+
|
23
|
+
# This is called from the accordion-group directive to add itself to the accordion
|
24
|
+
@addGroup = (groupScope) ->
|
25
|
+
that = this
|
26
|
+
@groups.push groupScope
|
27
|
+
groupScope.$on "$destroy", (event) ->
|
28
|
+
that.removeGroup groupScope
|
29
|
+
|
30
|
+
# This is called from the accordion-group directive when to remove itself
|
31
|
+
@removeGroup = (group) ->
|
32
|
+
index = @groups.indexOf(group)
|
33
|
+
@groups.splice index, 1 if index isnt -1
|
34
|
+
|
35
|
+
return this
|
36
|
+
])
|
37
|
+
|
38
|
+
# The accordion directive simply sets up the directive controller
|
39
|
+
# and adds an accordion CSS class to itself element.
|
40
|
+
.directive "accordion", ->
|
41
|
+
restrict: "EA"
|
42
|
+
controller: "AccordionController"
|
43
|
+
transclude: true
|
44
|
+
replace: false
|
45
|
+
templateUrl: 'rolodex_angular/template/accordion/accordion'
|
46
|
+
|
47
|
+
# The accordion-group directive indicates a block of html that will expand and collapse in an accordion
|
48
|
+
.directive "accordionGroup", ->
|
49
|
+
require: "^accordion" # We need this directive to be inside an accordion
|
50
|
+
restrict: "EA"
|
51
|
+
transclude: true # It transcludes the contents of the directive into the template
|
52
|
+
replace: true # The element containing the directive will be replaced with the template
|
53
|
+
templateUrl: 'rolodex_angular/template/accordion/accordion-group'
|
54
|
+
scope:
|
55
|
+
heading: "@" # Interpolate the heading attribute onto this scope
|
56
|
+
isOpen: "=?"
|
57
|
+
isDisabled: "=?"
|
58
|
+
|
59
|
+
controller: ->
|
60
|
+
@setHeading = (element) ->
|
61
|
+
@heading = element
|
62
|
+
|
63
|
+
link: (scope, element, attrs, accordionCtrl) ->
|
64
|
+
accordionCtrl.addGroup scope
|
65
|
+
scope.$watch "isOpen", (value) ->
|
66
|
+
accordionCtrl.closeOthers scope if value
|
67
|
+
return
|
68
|
+
|
69
|
+
scope.toggleOpen = ->
|
70
|
+
scope.isOpen = not scope.isOpen unless scope.isDisabled
|
71
|
+
|
72
|
+
# Use accordion-heading below an accordion-group to provide a heading containing HTML
|
73
|
+
# <accordion-group>
|
74
|
+
# <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
|
75
|
+
# </accordion-group>
|
76
|
+
.directive "accordionHeading", ->
|
77
|
+
restrict: "EA"
|
78
|
+
transclude: true # Grab the contents to be used as the heading
|
79
|
+
template: "" # In effect remove this element!
|
80
|
+
replace: true
|
81
|
+
require: "^accordionGroup"
|
82
|
+
link: (scope, element, attr, accordionGroupCtrl, transclude) ->
|
83
|
+
# Pass the heading to the accordion-group controller
|
84
|
+
# so that it can be transcluded into the right place in the template
|
85
|
+
# [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
|
86
|
+
accordionGroupCtrl.setHeading transclude(scope, (->))
|
87
|
+
|
88
|
+
# Use in the accordion-group template to indicate where you want the heading to be transcluded
|
89
|
+
# You must provide the property on the accordion-group controller that will hold the transcluded element
|
90
|
+
# <div class="accordion-group">
|
91
|
+
# <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
|
92
|
+
# ...
|
93
|
+
# </div>
|
94
|
+
.directive "accordionTransclude", ->
|
95
|
+
require: "^accordionGroup"
|
96
|
+
link: (scope, element, attr, controller) ->
|
97
|
+
scope.$watch (-> controller[attr.accordionTransclude]), (heading) ->
|
98
|
+
if heading
|
99
|
+
element.html ""
|
100
|
+
element.append heading
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#= require 'rolodex_angular/template/alert/alert'
|
2
|
+
|
3
|
+
angular.module('rolodex.alert', [])
|
4
|
+
|
5
|
+
.controller('AlertController', ['$scope', '$attrs', ($scope, $attrs) ->
|
6
|
+
$scope.closeable = 'close' of $attrs
|
7
|
+
])
|
8
|
+
|
9
|
+
.directive 'alert', ->
|
10
|
+
restrict: 'EA'
|
11
|
+
controller: 'AlertController'
|
12
|
+
templateUrl: 'rolodex_angular/template/alert/alert'
|
13
|
+
transclude: true
|
14
|
+
replace: true
|
15
|
+
scope:
|
16
|
+
type: '@'
|
17
|
+
close: '&'
|
@@ -0,0 +1,59 @@
|
|
1
|
+
angular.module("rolodex.buttons", [])
|
2
|
+
|
3
|
+
.constant("buttonConfig", activeClass: "active", toggleEvent: "click")
|
4
|
+
|
5
|
+
.controller("ButtonsController", [
|
6
|
+
"buttonConfig"
|
7
|
+
(buttonConfig) ->
|
8
|
+
@activeClass = buttonConfig.activeClass or "active"
|
9
|
+
@toggleEvent = buttonConfig.toggleEvent or "click"
|
10
|
+
|
11
|
+
return this
|
12
|
+
])
|
13
|
+
|
14
|
+
.directive("btnRadio", ->
|
15
|
+
require: [
|
16
|
+
"btnRadio"
|
17
|
+
"ngModel"
|
18
|
+
]
|
19
|
+
controller: "ButtonsController"
|
20
|
+
link: (scope, element, attrs, ctrls) ->
|
21
|
+
buttonsCtrl = ctrls[0]
|
22
|
+
ngModelCtrl = ctrls[1]
|
23
|
+
ngModelCtrl.$render = ->
|
24
|
+
element.toggleClass buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))
|
25
|
+
|
26
|
+
element.bind buttonsCtrl.toggleEvent, ->
|
27
|
+
isActive = element.hasClass(buttonsCtrl.activeClass)
|
28
|
+
if not isActive or angular.isDefined(attrs.uncheckable)
|
29
|
+
scope.$apply ->
|
30
|
+
ngModelCtrl.$setViewValue (if isActive then null else scope.$eval(attrs.btnRadio))
|
31
|
+
ngModelCtrl.$render()
|
32
|
+
)
|
33
|
+
|
34
|
+
.directive "btnCheckbox", ->
|
35
|
+
require: [
|
36
|
+
"btnCheckbox"
|
37
|
+
"ngModel"
|
38
|
+
]
|
39
|
+
controller: "ButtonsController"
|
40
|
+
link: (scope, element, attrs, ctrls) ->
|
41
|
+
getTrueValue = ->
|
42
|
+
getCheckboxValue attrs.btnCheckboxTrue, true
|
43
|
+
getFalseValue = ->
|
44
|
+
getCheckboxValue attrs.btnCheckboxFalse, false
|
45
|
+
getCheckboxValue = (attributeValue, defaultValue) ->
|
46
|
+
val = scope.$eval(attributeValue)
|
47
|
+
(if angular.isDefined(val) then val else defaultValue)
|
48
|
+
buttonsCtrl = ctrls[0]
|
49
|
+
ngModelCtrl = ctrls[1]
|
50
|
+
|
51
|
+
#model -> UI
|
52
|
+
ngModelCtrl.$render = ->
|
53
|
+
element.toggleClass buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())
|
54
|
+
|
55
|
+
#ui->model
|
56
|
+
element.bind buttonsCtrl.toggleEvent, ->
|
57
|
+
scope.$apply ->
|
58
|
+
ngModelCtrl.$setViewValue (if element.hasClass(buttonsCtrl.activeClass) then getFalseValue() else getTrueValue())
|
59
|
+
ngModelCtrl.$render()
|
@@ -0,0 +1,65 @@
|
|
1
|
+
angular.module("rolodex.collapse", ["rolodex.transition"])
|
2
|
+
|
3
|
+
.directive "collapse", [
|
4
|
+
"$transition"
|
5
|
+
($transition) ->
|
6
|
+
return link: (scope, element, attrs) ->
|
7
|
+
doTransition = (change) ->
|
8
|
+
newTransitionDone = ->
|
9
|
+
|
10
|
+
# Make sure it's this transition, otherwise, leave it alone.
|
11
|
+
currentTransition = `undefined` if currentTransition is newTransition
|
12
|
+
|
13
|
+
newTransition = $transition(element, change)
|
14
|
+
|
15
|
+
currentTransition.cancel() if currentTransition
|
16
|
+
|
17
|
+
currentTransition = newTransition
|
18
|
+
|
19
|
+
newTransition.then(newTransitionDone, newTransitionDone)
|
20
|
+
|
21
|
+
return newTransition
|
22
|
+
return
|
23
|
+
expand = ->
|
24
|
+
if initialAnimSkip
|
25
|
+
initialAnimSkip = false
|
26
|
+
expandDone()
|
27
|
+
else
|
28
|
+
element.removeClass("collapse").addClass "collapsing"
|
29
|
+
doTransition(height: element[0].scrollHeight + "px").then expandDone
|
30
|
+
return
|
31
|
+
expandDone = ->
|
32
|
+
element.removeClass "collapsing"
|
33
|
+
element.addClass "collapse in"
|
34
|
+
element.css height: "auto"
|
35
|
+
return
|
36
|
+
collapse = ->
|
37
|
+
if initialAnimSkip
|
38
|
+
initialAnimSkip = false
|
39
|
+
collapseDone()
|
40
|
+
element.css height: 0
|
41
|
+
else
|
42
|
+
|
43
|
+
# CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
|
44
|
+
element.css height: element[0].scrollHeight + "px"
|
45
|
+
|
46
|
+
#trigger reflow so a browser realizes that height was updated from auto to a specific value
|
47
|
+
x = element[0].offsetWidth
|
48
|
+
element.removeClass("collapse in").addClass "collapsing"
|
49
|
+
doTransition(height: 0).then collapseDone
|
50
|
+
return
|
51
|
+
collapseDone = ->
|
52
|
+
element.removeClass "collapsing"
|
53
|
+
element.addClass "collapse"
|
54
|
+
return
|
55
|
+
initialAnimSkip = true
|
56
|
+
currentTransition = undefined
|
57
|
+
scope.$watch attrs.collapse, (shouldCollapse) ->
|
58
|
+
if shouldCollapse
|
59
|
+
collapse()
|
60
|
+
else
|
61
|
+
expand()
|
62
|
+
return
|
63
|
+
|
64
|
+
return
|
65
|
+
]
|
@@ -0,0 +1,125 @@
|
|
1
|
+
angular.module('rolodex.dateparser', [])
|
2
|
+
|
3
|
+
.service "dateParser", [
|
4
|
+
"$locale"
|
5
|
+
"orderByFilter"
|
6
|
+
($locale, orderByFilter) ->
|
7
|
+
createParser = (format) ->
|
8
|
+
map = []
|
9
|
+
regex = format.split("")
|
10
|
+
angular.forEach formatCodeToRegex, (data, code) ->
|
11
|
+
index = format.indexOf(code)
|
12
|
+
if index > -1
|
13
|
+
format = format.split("")
|
14
|
+
regex[index] = "(" + data.regex + ")"
|
15
|
+
format[index] = "$" # Custom symbol to define consumed part of format
|
16
|
+
i = index + 1
|
17
|
+
n = index + code.length
|
18
|
+
|
19
|
+
while i < n
|
20
|
+
regex[i] = ""
|
21
|
+
format[i] = "$"
|
22
|
+
i++
|
23
|
+
format = format.join("")
|
24
|
+
map.push
|
25
|
+
index: index
|
26
|
+
apply: data.apply
|
27
|
+
|
28
|
+
return
|
29
|
+
|
30
|
+
regex: new RegExp("^" + regex.join("") + "$")
|
31
|
+
map: orderByFilter(map, "index")
|
32
|
+
|
33
|
+
# Check if date is valid for specific month (and year for February).
|
34
|
+
# Month: 0 = Jan, 1 = Feb, etc
|
35
|
+
isValid = (year, month, date) ->
|
36
|
+
return date is 29 and ((year % 4 is 0 and year % 100 isnt 0) or year % 400 is 0) if month is 1 and date > 28
|
37
|
+
return date < 31 if month is 3 or month is 5 or month is 8 or month is 10
|
38
|
+
true
|
39
|
+
@parsers = {}
|
40
|
+
formatCodeToRegex =
|
41
|
+
yyyy:
|
42
|
+
regex: "\\d{4}"
|
43
|
+
apply: (value) ->
|
44
|
+
@year = +value
|
45
|
+
return
|
46
|
+
|
47
|
+
yy:
|
48
|
+
regex: "\\d{2}"
|
49
|
+
apply: (value) ->
|
50
|
+
@year = +value + 2000
|
51
|
+
return
|
52
|
+
|
53
|
+
y:
|
54
|
+
regex: "\\d{1,4}"
|
55
|
+
apply: (value) ->
|
56
|
+
@year = +value
|
57
|
+
return
|
58
|
+
|
59
|
+
MMMM:
|
60
|
+
regex: $locale.DATETIME_FORMATS.MONTH.join("|")
|
61
|
+
apply: (value) ->
|
62
|
+
@month = $locale.DATETIME_FORMATS.MONTH.indexOf(value)
|
63
|
+
return
|
64
|
+
|
65
|
+
MMM:
|
66
|
+
regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|")
|
67
|
+
apply: (value) ->
|
68
|
+
@month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value)
|
69
|
+
return
|
70
|
+
|
71
|
+
MM:
|
72
|
+
regex: "0[1-9]|1[0-2]"
|
73
|
+
apply: (value) ->
|
74
|
+
@month = value - 1
|
75
|
+
return
|
76
|
+
|
77
|
+
M:
|
78
|
+
regex: "[1-9]|1[0-2]"
|
79
|
+
apply: (value) ->
|
80
|
+
@month = value - 1
|
81
|
+
return
|
82
|
+
|
83
|
+
dd:
|
84
|
+
regex: "[0-2][0-9]{1}|3[0-1]{1}"
|
85
|
+
apply: (value) ->
|
86
|
+
@date = +value
|
87
|
+
return
|
88
|
+
|
89
|
+
d:
|
90
|
+
regex: "[1-2]?[0-9]{1}|3[0-1]{1}"
|
91
|
+
apply: (value) ->
|
92
|
+
@date = +value
|
93
|
+
|
94
|
+
EEEE:
|
95
|
+
regex: $locale.DATETIME_FORMATS.DAY.join("|")
|
96
|
+
|
97
|
+
EEE:
|
98
|
+
regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|")
|
99
|
+
|
100
|
+
@parse = (input, format) ->
|
101
|
+
return input if not angular.isString(input) or not format
|
102
|
+
format = $locale.DATETIME_FORMATS[format] or format
|
103
|
+
@parsers[format] = createParser(format) unless @parsers[format]
|
104
|
+
parser = @parsers[format]
|
105
|
+
regex = parser.regex
|
106
|
+
map = parser.map
|
107
|
+
results = input.match(regex)
|
108
|
+
if results and results.length
|
109
|
+
fields =
|
110
|
+
year: 1900
|
111
|
+
month: 0
|
112
|
+
date: 1
|
113
|
+
hours: 0
|
114
|
+
|
115
|
+
dt = undefined
|
116
|
+
i = 1
|
117
|
+
n = results.length
|
118
|
+
|
119
|
+
while i < n
|
120
|
+
mapper = map[i - 1]
|
121
|
+
mapper.apply.call fields, results[i] if mapper.apply
|
122
|
+
i++
|
123
|
+
dt = new Date(fields.year, fields.month, fields.date, fields.hours) if isValid(fields.year, fields.month, fields.date)
|
124
|
+
dt
|
125
|
+
]
|