rails-fort 0.1.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +55 -0
- data/.gitignore +32 -3
- data/.rspec +1 -0
- data/.rubocop.yml +35 -0
- data/CHANGELOG.md +43 -0
- data/CODE_OF_CONDUCT.md +1 -0
- data/Gemfile +7 -2
- data/README.md +87 -45
- data/Rakefile +3 -1
- data/UPGRADE_GUIDE.md +107 -0
- data/app/assets/javascripts/fort.js +280 -0
- data/app/assets/javascripts/rails_fort.js.erb +29 -20
- data/app/assets/stylesheets/fort.css +52 -0
- data/lib/rails/fort/version.rb +3 -1
- data/lib/rails/fort.rb +2 -0
- data/rails-fort.gemspec +27 -17
- metadata +78 -22
- data/.travis.yml +0 -8
- data/npm-debug.log +0 -18
- data/vendor/assets/javascripts/fort.min.js +0 -1
- data/vendor/assets/stylesheets/fort.min.css +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4def9cb0b3f3e14b33e1b34efa92e70dba9d7aea7f57cfe69c1d141cbfc5f149
|
|
4
|
+
data.tar.gz: 17bace62f5d924ecf13daf02f8836eb48f3a3e07ee96c7f14235988d1c5d00cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5a4098a1bb92800febb3bd8ac7df48994b2e5d2b79a8eb144c13dbd98f4f7f5c91d57a2d1071777c5faecb91b1e8c1637e07e0f0bacef54ea75235f35278e6e
|
|
7
|
+
data.tar.gz: 0e54e8564ebceee75c96101308abf3bb31b293def4ba571e098f68366ebf68fae0f0a8f4b2b8966753be216be70536e2105afc2ca13a62e5e4dada221e176194
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
ruby: ['3.0', '3.1', '3.2', '3.3']
|
|
16
|
+
rails: ['6.0', '6.1', '7.0', '7.1', '7.2', '8.0']
|
|
17
|
+
exclude:
|
|
18
|
+
# Rails 7.2+ requires Ruby 3.1+
|
|
19
|
+
- ruby: '3.0'
|
|
20
|
+
rails: '7.2'
|
|
21
|
+
- ruby: '3.0'
|
|
22
|
+
rails: '8.0'
|
|
23
|
+
|
|
24
|
+
env:
|
|
25
|
+
RAILS_VERSION: ${{ matrix.rails }}
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
ruby-version: ${{ matrix.ruby }}
|
|
34
|
+
bundler-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: bundle exec rake
|
|
38
|
+
|
|
39
|
+
- name: Run RuboCop
|
|
40
|
+
run: bundle exec rubocop
|
|
41
|
+
|
|
42
|
+
security:
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v4
|
|
47
|
+
|
|
48
|
+
- name: Set up Ruby
|
|
49
|
+
uses: ruby/setup-ruby@v1
|
|
50
|
+
with:
|
|
51
|
+
ruby-version: '3.3'
|
|
52
|
+
bundler-cache: true
|
|
53
|
+
|
|
54
|
+
- name: Security audit
|
|
55
|
+
run: bundle exec bundle-audit --update
|
data/.gitignore
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
|
+
## Ruby/Bundler
|
|
1
2
|
/.bundle/
|
|
2
|
-
|
|
3
|
+
/vendor/bundle/
|
|
3
4
|
/Gemfile.lock
|
|
5
|
+
|
|
6
|
+
## Documentation
|
|
7
|
+
/.yardoc/
|
|
4
8
|
/_yardoc/
|
|
5
|
-
/coverage/
|
|
6
9
|
/doc/
|
|
7
|
-
/
|
|
10
|
+
/rdoc/
|
|
11
|
+
|
|
12
|
+
## Testing
|
|
13
|
+
/coverage/
|
|
8
14
|
/spec/reports/
|
|
15
|
+
/test/tmp/
|
|
16
|
+
/test/version_tmp/
|
|
17
|
+
|
|
18
|
+
## Build artifacts
|
|
19
|
+
/pkg/
|
|
9
20
|
/tmp/
|
|
21
|
+
*.gem
|
|
22
|
+
|
|
23
|
+
## IDE and OS files
|
|
24
|
+
.DS_Store
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
28
|
+
*.swo
|
|
29
|
+
*~
|
|
30
|
+
.ruby-version
|
|
31
|
+
.ruby-gemset
|
|
32
|
+
|
|
33
|
+
## Environment
|
|
34
|
+
.env
|
|
35
|
+
.env.local
|
|
36
|
+
|
|
37
|
+
## Logs
|
|
38
|
+
npm-debug.log
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.0
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
Exclude:
|
|
6
|
+
- 'vendor/**/*'
|
|
7
|
+
- 'bin/**/*'
|
|
8
|
+
- 'app/assets/javascripts/fort.js'
|
|
9
|
+
|
|
10
|
+
Style/Documentation:
|
|
11
|
+
Enabled: false
|
|
12
|
+
|
|
13
|
+
Style/StringLiterals:
|
|
14
|
+
Enabled: true
|
|
15
|
+
EnforcedStyle: double_quotes
|
|
16
|
+
|
|
17
|
+
Style/FrozenStringLiteralComment:
|
|
18
|
+
Enabled: true
|
|
19
|
+
EnforcedStyle: always
|
|
20
|
+
|
|
21
|
+
Layout/LineLength:
|
|
22
|
+
Max: 120
|
|
23
|
+
Exclude:
|
|
24
|
+
- '*.gemspec'
|
|
25
|
+
|
|
26
|
+
Metrics/BlockLength:
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
- '*.gemspec'
|
|
30
|
+
|
|
31
|
+
Gemspec/DevelopmentDependencies:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
Gemspec/AddRuntimeDependency:
|
|
35
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.0] - 2026-05-30
|
|
6
|
+
|
|
7
|
+
First modern release on RubyGems.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- New vanilla JavaScript implementation (`fort.js`) — no jQuery, no `document.body` rewriting
|
|
12
|
+
- `fort.css` as a first-class stylesheet (include via `*= require fort`)
|
|
13
|
+
- Support for `fort-ignore` class in addition to `ignore`
|
|
14
|
+
- Accessible progress bar attributes (`role="progressbar"`, `aria-*`)
|
|
15
|
+
- Explicit `railties` runtime dependency (>= 6.0, < 9.0)
|
|
16
|
+
- GitHub Actions CI, RuboCop, bundler-audit, RSpec
|
|
17
|
+
- CHANGELOG, UPGRADE_GUIDE, and modern README
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Breaking (JS):** Replaced legacy vendored `fort.min.js` with `FortProgress` class
|
|
22
|
+
- **Breaking (Ruby):** Minimum Ruby 3.0, Rails 6.0+
|
|
23
|
+
- `config/fort.yml` format unchanged (`type`, `value`, `height`, `duration`, `alignment`)
|
|
24
|
+
- Progress bar DOM uses `.fort-bar` (legacy `.top-one` / `.top-two` classes retained in CSS for compatibility)
|
|
25
|
+
|
|
26
|
+
### Removed
|
|
27
|
+
|
|
28
|
+
- jQuery dependency
|
|
29
|
+
- Legacy vendor `fort.min.js` and `fort.min.css`
|
|
30
|
+
- Travis CI
|
|
31
|
+
|
|
32
|
+
### Notes
|
|
33
|
+
|
|
34
|
+
- Original upstream Fort.js GitHub repository is unavailable; JS is maintained in this gem
|
|
35
|
+
|
|
36
|
+
## [0.2.0] - Previous Release
|
|
37
|
+
|
|
38
|
+
- jQuery-based integration with vendored Fort.js
|
|
39
|
+
- Form completion progress bar with `config/fort.yml`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
For upgrade instructions, see [UPGRADE_GUIDE.md](UPGRADE_GUIDE.md)
|
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -11,3 +11,4 @@ Project maintainers have the right and responsibility to remove, edit, or reject
|
|
|
11
11
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
|
12
12
|
|
|
13
13
|
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
|
14
|
+
|
data/Gemfile
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
2
4
|
|
|
3
|
-
# Specify your gem's dependencies in rails-fort.gemspec
|
|
4
5
|
gemspec
|
|
6
|
+
|
|
7
|
+
if (rails_version = ENV.fetch("RAILS_VERSION", nil))
|
|
8
|
+
gem "railties", "~> #{rails_version}.0"
|
|
9
|
+
end
|
data/README.md
CHANGED
|
@@ -1,96 +1,138 @@
|
|
|
1
1
|
# Rails::Fort
|
|
2
2
|
|
|
3
|
-
[](https://hakiri.io/github/ethirajsrinivasan/rails-fort/master)
|
|
3
|
+
[](https://github.com/ethirajsrinivasan/rails-fort/actions/workflows/ci.yml)
|
|
4
|
+
[](https://badge.fury.io/rb/rails-fort)
|
|
6
5
|
|
|
6
|
+
Modern progress bar for form completion
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- Ruby >= 3.0
|
|
11
|
+
- Rails >= 6.0
|
|
12
|
+
- No jQuery required
|
|
9
13
|
|
|
10
14
|
## Installation
|
|
11
15
|
|
|
12
16
|
Add this line to your application's Gemfile:
|
|
13
17
|
|
|
14
18
|
```ruby
|
|
15
|
-
gem 'rails-fort'
|
|
19
|
+
gem 'rails-fort', '~> 1.0'
|
|
16
20
|
```
|
|
17
21
|
|
|
18
22
|
And then execute:
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
```bash
|
|
25
|
+
bundle install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Asset Pipeline Setup
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
**For Rails 6.x / 7.x with Sprockets:**
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
In `app/assets/javascripts/application.js`:
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
```javascript
|
|
35
|
+
//= require rails_fort
|
|
36
|
+
```
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
In `app/assets/stylesheets/application.css`:
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
```css
|
|
41
|
+
*= require fort
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**For Rails 7+ with Import Maps:**
|
|
45
|
+
|
|
46
|
+
Add to `config/importmap.rb`:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
pin "rails_fort", to: "rails_fort.js"
|
|
50
|
+
pin "fort", to: "fort.js"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Import in `application.js`:
|
|
31
54
|
|
|
32
|
-
|
|
55
|
+
```javascript
|
|
56
|
+
import "rails_fort"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Include `fort.css` through your stylesheet pipeline or asset host.
|
|
33
60
|
|
|
34
|
-
|
|
61
|
+
## Usage
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
Rails-Fort tracks `input`, `textarea`, and `select` fields inside forms and shows a fixed progress bar as the user completes the form.
|
|
37
64
|
|
|
38
|
-
|
|
65
|
+
### Exclude fields
|
|
39
66
|
|
|
40
|
-
|
|
67
|
+
Add `ignore` or `fort-ignore` to skip a field:
|
|
41
68
|
|
|
69
|
+
```html
|
|
70
|
+
<input type="text" class="ignore">
|
|
71
|
+
```
|
|
42
72
|
|
|
43
|
-
|
|
73
|
+
### Configuration (`config/fort.yml`)
|
|
44
74
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
75
|
+
```yaml
|
|
76
|
+
height: '20px'
|
|
77
|
+
duration: '3s'
|
|
78
|
+
alignment: 'bottom'
|
|
79
|
+
type: 'solid'
|
|
80
|
+
value: '#009DFF'
|
|
81
|
+
```
|
|
50
82
|
|
|
83
|
+
### Effects
|
|
51
84
|
|
|
52
|
-
|
|
85
|
+
**Solid**
|
|
53
86
|
|
|
54
|
-
|
|
87
|
+
```yaml
|
|
88
|
+
type: 'solid'
|
|
89
|
+
value: '#009DFF'
|
|
90
|
+
```
|
|
55
91
|
|
|
56
|
-
|
|
57
|
-
value: '#009DFF'
|
|
92
|
+
**Gradient** (two colors)
|
|
58
93
|
|
|
59
|
-
|
|
94
|
+
```yaml
|
|
95
|
+
type: 'gradient'
|
|
96
|
+
value: ['#009DFF', '#47B9FF']
|
|
97
|
+
```
|
|
60
98
|
|
|
61
|
-
|
|
62
|
-
value: ["#009DFF", "#47B9FF"]
|
|
99
|
+
**Sections**
|
|
63
100
|
|
|
64
|
-
|
|
101
|
+
```yaml
|
|
102
|
+
type: 'sections'
|
|
103
|
+
value: ['#009DFF', '#4AF2A1', '#FB5229']
|
|
104
|
+
```
|
|
65
105
|
|
|
66
|
-
|
|
106
|
+
**Flash**
|
|
67
107
|
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
```yaml
|
|
109
|
+
type: 'flash'
|
|
110
|
+
value: ['#009DFF', '#000', '#6638F0']
|
|
111
|
+
```
|
|
70
112
|
|
|
71
|
-
|
|
113
|
+
**Merge**
|
|
72
114
|
|
|
73
|
-
|
|
74
|
-
|
|
115
|
+
```yaml
|
|
116
|
+
type: 'merge'
|
|
117
|
+
value: '#009DFF'
|
|
118
|
+
```
|
|
75
119
|
|
|
76
|
-
|
|
120
|
+
## Upgrading
|
|
77
121
|
|
|
78
|
-
|
|
79
|
-
value: '#009DFF'
|
|
122
|
+
Upgrading from the legacy **0.x** gem? See [UPGRADE_GUIDE.md](UPGRADE_GUIDE.md) for **1.0.0**.
|
|
80
123
|
|
|
81
|
-
|
|
124
|
+
## JavaScript
|
|
82
125
|
|
|
126
|
+
The progress bar is implemented in vanilla JavaScript (`app/assets/javascripts/fort.js`) and vendored inside this gem. The original [Fort.js](https://github.com/idriskhenchil/Fort.js) repository by Idris Khenchil is no longer available; this gem maintains a compatible `fort.yml` API with a new implementation.
|
|
83
127
|
|
|
84
128
|
## Contributing
|
|
85
129
|
|
|
86
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/ethirajsrinivasan/rails-fort.
|
|
87
|
-
|
|
88
|
-
##Thanks
|
|
130
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ethirajsrinivasan/rails-fort. Contributors are expected to adhere to the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.
|
|
89
131
|
|
|
90
|
-
Thanks
|
|
132
|
+
## Thanks
|
|
91
133
|
|
|
134
|
+
Thanks to Idris Khenchil for the original Fort.js form progress bar concept.
|
|
92
135
|
|
|
93
136
|
## License
|
|
94
137
|
|
|
95
138
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
|
96
|
-
|
data/Rakefile
CHANGED
data/UPGRADE_GUIDE.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Upgrade Guide: Rails-Fort 0.x to 1.0.0
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Rails-Fort **1.0.0** is the first modern release on RubyGems. It combines Ruby/Rails modernization (Ruby 3.0+, Rails 6.0+) with a **rewritten JavaScript engine** while keeping the same `config/fort.yml` format.
|
|
6
|
+
|
|
7
|
+
## What Changed
|
|
8
|
+
|
|
9
|
+
### Ruby & Rails
|
|
10
|
+
|
|
11
|
+
| Component | 0.x | 1.0.0 |
|
|
12
|
+
|-----------|-----|-------|
|
|
13
|
+
| Ruby | >= 2.7 (varied) | >= 3.0 |
|
|
14
|
+
| Rails | >= 4.2 | >= 6.0 |
|
|
15
|
+
|
|
16
|
+
### JavaScript
|
|
17
|
+
|
|
18
|
+
| Topic | 0.x | 1.0.0 |
|
|
19
|
+
|-------|-----|-------|
|
|
20
|
+
| jQuery | Required | **Not required** |
|
|
21
|
+
| Implementation | Vendored legacy `fort.min.js` | New `fort.js` (`FortProgress`) |
|
|
22
|
+
| CSS | Bundled minified vendor file | `*= require fort` in your stylesheet manifest |
|
|
23
|
+
| DOM behavior | Rewrote `document.body` innerHTML | Inserts progress bar elements only |
|
|
24
|
+
| Ignore class | `ignore` | `ignore` or `fort-ignore` |
|
|
25
|
+
| Upstream repo | idriskhenchil/Fort.js (now 404) | Maintained in this gem |
|
|
26
|
+
|
|
27
|
+
### Unchanged
|
|
28
|
+
|
|
29
|
+
- `config/fort.yml` keys: `height`, `duration`, `alignment`, `type`, `value`
|
|
30
|
+
- Effect types: `solid`, `gradient`, `sections`, `flash`, `merge`
|
|
31
|
+
- `//= require rails_fort` in `application.js`
|
|
32
|
+
|
|
33
|
+
## Upgrade Steps
|
|
34
|
+
|
|
35
|
+
### 1. Update Gemfile
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
gem 'rails-fort', '~> 1.0'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
bundle update rails-fort
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Add stylesheet (new in 1.0)
|
|
46
|
+
|
|
47
|
+
In `app/assets/stylesheets/application.css` (or equivalent):
|
|
48
|
+
|
|
49
|
+
```css
|
|
50
|
+
*= require fort
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Remove jQuery requirement
|
|
54
|
+
|
|
55
|
+
You no longer need jQuery for rails-fort. Remove any load order that existed only for this gem.
|
|
56
|
+
|
|
57
|
+
### 4. Keep `config/fort.yml`
|
|
58
|
+
|
|
59
|
+
Existing configuration should work as-is, for example:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
height: '20px'
|
|
63
|
+
duration: '3s'
|
|
64
|
+
alignment: 'bottom'
|
|
65
|
+
type: 'solid'
|
|
66
|
+
value: '#009DFF'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 5. Test your forms
|
|
70
|
+
|
|
71
|
+
1. Load a page with a form
|
|
72
|
+
2. Confirm the progress bar appears (top or bottom per `alignment`)
|
|
73
|
+
3. Fill fields and verify width/color effects
|
|
74
|
+
4. Confirm fields with class `ignore` are skipped
|
|
75
|
+
|
|
76
|
+
## Troubleshooting
|
|
77
|
+
|
|
78
|
+
### Progress bar not visible
|
|
79
|
+
|
|
80
|
+
- Ensure **both** JS and CSS are included (`rails_fort` + `fort` stylesheet)
|
|
81
|
+
- Check the browser console for errors
|
|
82
|
+
- Verify `config/fort.yml` is valid YAML
|
|
83
|
+
|
|
84
|
+
### Custom CSS targeting old markup
|
|
85
|
+
|
|
86
|
+
1.0 still applies `.top-one` and `.top-two` on bar elements for compatibility. Prefer `.fort-bar` for new custom styles.
|
|
87
|
+
|
|
88
|
+
### Turbo / Turbolinks
|
|
89
|
+
|
|
90
|
+
Re-initialize on page change if needed:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
document.addEventListener("turbo:load", function () {
|
|
94
|
+
if (window._railsFortInstance) {
|
|
95
|
+
window._railsFortInstance.destroy();
|
|
96
|
+
window._railsFortInstance = new FortProgress(/* your config */);
|
|
97
|
+
window._railsFortInstance.init();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For Sprockets-only apps, a full page load re-runs `rails_fort.js.erb` automatically.
|
|
103
|
+
|
|
104
|
+
## Getting Help
|
|
105
|
+
|
|
106
|
+
- [GitHub Issues](https://github.com/ethirajsrinivasan/rails-fort/issues)
|
|
107
|
+
- [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rails-Fort — form completion progress bar (vanilla JavaScript).
|
|
3
|
+
*
|
|
4
|
+
* Initialized from rails_fort.js.erb with config from config/fort.yml.
|
|
5
|
+
*/
|
|
6
|
+
class FortProgress {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.config = {
|
|
9
|
+
type: config.type || "solid",
|
|
10
|
+
value: config.value ?? "#009DFF",
|
|
11
|
+
height: config.height || "4px",
|
|
12
|
+
duration: config.duration || "1s",
|
|
13
|
+
alignment: config.alignment || "top"
|
|
14
|
+
};
|
|
15
|
+
this.bars = [];
|
|
16
|
+
this.containers = [];
|
|
17
|
+
this._sortedFlashColors = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
init() {
|
|
21
|
+
this._prepareForms();
|
|
22
|
+
this._buildBars();
|
|
23
|
+
this._bindFields();
|
|
24
|
+
this._update();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
destroy() {
|
|
28
|
+
this._unbindFields();
|
|
29
|
+
this.bars.forEach((bar) => bar.remove());
|
|
30
|
+
this.bars = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_prepareForms() {
|
|
34
|
+
document.querySelectorAll("form").forEach((form) => {
|
|
35
|
+
if (form.dataset.fortWrapped === "true") return;
|
|
36
|
+
|
|
37
|
+
const wrapper = document.createElement("div");
|
|
38
|
+
wrapper.className = "fort-form form";
|
|
39
|
+
form.parentNode.insertBefore(wrapper, form);
|
|
40
|
+
wrapper.appendChild(form);
|
|
41
|
+
form.dataset.fortWrapped = "true";
|
|
42
|
+
this.containers.push(wrapper);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
document.querySelectorAll(".fort-form, .form").forEach((container) => {
|
|
46
|
+
if (!this.containers.includes(container)) {
|
|
47
|
+
this.containers.push(container);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
_buildBars() {
|
|
53
|
+
this.bars.forEach((bar) => bar.remove());
|
|
54
|
+
this.bars = [];
|
|
55
|
+
|
|
56
|
+
if (this.config.type === "merge") {
|
|
57
|
+
this.bars.push(this._createBar("fort-bar top-one"));
|
|
58
|
+
this.bars.push(this._createBar("fort-bar fort-bar--secondary top-two"));
|
|
59
|
+
} else {
|
|
60
|
+
this.bars.push(this._createBar("fort-bar top-one"));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const isBottom = this.config.alignment === "bottom";
|
|
64
|
+
|
|
65
|
+
this.bars.forEach((bar) => {
|
|
66
|
+
bar.style.height = this.config.height;
|
|
67
|
+
bar.style.transitionDuration = this.config.duration;
|
|
68
|
+
|
|
69
|
+
if (isBottom) {
|
|
70
|
+
bar.classList.add("fort-bar--bottom");
|
|
71
|
+
bar.style.top = "auto";
|
|
72
|
+
bar.style.bottom = "0";
|
|
73
|
+
} else {
|
|
74
|
+
bar.style.top = "0";
|
|
75
|
+
bar.style.bottom = "auto";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
document.body.appendChild(bar);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
_createBar(className) {
|
|
83
|
+
const bar = document.createElement("div");
|
|
84
|
+
bar.className = className;
|
|
85
|
+
bar.setAttribute("role", "progressbar");
|
|
86
|
+
bar.setAttribute("aria-valuemin", "0");
|
|
87
|
+
bar.setAttribute("aria-valuemax", "100");
|
|
88
|
+
|
|
89
|
+
const fill = document.createElement("div");
|
|
90
|
+
fill.className = "fort-bar__fill colors";
|
|
91
|
+
bar.appendChild(fill);
|
|
92
|
+
|
|
93
|
+
return bar;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_bindFields() {
|
|
97
|
+
this._getFields().forEach((field) => {
|
|
98
|
+
field.addEventListener("input", this._update);
|
|
99
|
+
field.addEventListener("change", this._update);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
_unbindFields() {
|
|
104
|
+
this._getFields().forEach((field) => {
|
|
105
|
+
field.removeEventListener("input", this._update);
|
|
106
|
+
field.removeEventListener("change", this._update);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_getFields() {
|
|
111
|
+
const fields = [];
|
|
112
|
+
|
|
113
|
+
this.containers.forEach((container) => {
|
|
114
|
+
container.querySelectorAll("input, textarea, select").forEach((field) => {
|
|
115
|
+
if (this._shouldTrack(field)) {
|
|
116
|
+
fields.push(field);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return fields;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_shouldTrack(field) {
|
|
125
|
+
const type = (field.type || "").toLowerCase();
|
|
126
|
+
|
|
127
|
+
if (type === "button" || type === "submit" || type === "hidden") {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (field.classList.contains("ignore") || field.classList.contains("fort-ignore")) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_isFilled(field) {
|
|
139
|
+
if (field.type === "checkbox" || field.type === "radio") {
|
|
140
|
+
return field.checked;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return String(field.value || "").trim().length > 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
_getCounts() {
|
|
147
|
+
const fields = this._getFields();
|
|
148
|
+
const total = fields.length;
|
|
149
|
+
const filled = fields.filter((field) => this._isFilled(field)).length;
|
|
150
|
+
|
|
151
|
+
return { total, filled, percent: total === 0 ? 0 : (filled / total) * 100 };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_update = () => {
|
|
155
|
+
const { total, filled, percent } = this._getCounts();
|
|
156
|
+
const unfilled = total - filled;
|
|
157
|
+
|
|
158
|
+
this.bars.forEach((bar) => {
|
|
159
|
+
bar.setAttribute("aria-valuenow", String(Math.round(percent)));
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
switch (this.config.type) {
|
|
163
|
+
case "gradient":
|
|
164
|
+
this._applyGradient(percent);
|
|
165
|
+
break;
|
|
166
|
+
case "sections":
|
|
167
|
+
this._applySections();
|
|
168
|
+
break;
|
|
169
|
+
case "flash":
|
|
170
|
+
this._applyFlash(total, unfilled);
|
|
171
|
+
break;
|
|
172
|
+
case "merge":
|
|
173
|
+
this._applyMerge(percent);
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
this._applySolid(percent);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
_applySolid(percent) {
|
|
181
|
+
const bar = this.bars[0];
|
|
182
|
+
const fill = bar.querySelector(".fort-bar__fill");
|
|
183
|
+
|
|
184
|
+
bar.style.width = `${percent}%`;
|
|
185
|
+
fill.style.background = this._colorValue();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
_applyGradient(percent) {
|
|
189
|
+
const colors = this._colorArray();
|
|
190
|
+
|
|
191
|
+
if (colors.length < 2) {
|
|
192
|
+
this._applySolid(percent);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const bar = this.bars[0];
|
|
197
|
+
const fill = bar.querySelector(".fort-bar__fill");
|
|
198
|
+
|
|
199
|
+
bar.style.width = `${percent}%`;
|
|
200
|
+
fill.style.background = `linear-gradient(to right, ${colors[0]}, ${colors[1]})`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
_applySections() {
|
|
204
|
+
const colors = this._colorArray();
|
|
205
|
+
|
|
206
|
+
if (colors.length === 0) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const { percent } = this._getCounts();
|
|
211
|
+
const bar = this.bars[0];
|
|
212
|
+
const fill = bar.querySelector(".fort-bar__fill");
|
|
213
|
+
const stops = [];
|
|
214
|
+
|
|
215
|
+
colors.forEach((color, index) => {
|
|
216
|
+
const stop = Math.floor((1000 * (index + 1)) / colors.length) / 10;
|
|
217
|
+
stops.push(`${color} ${stop}%`);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
bar.style.width = `${percent}%`;
|
|
221
|
+
fill.style.background = `linear-gradient(to right, ${stops.join(", ")})`;
|
|
222
|
+
fill.style.width = "100%";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_applyFlash(total, unfilled) {
|
|
226
|
+
const colors = this._colorArray().slice().sort();
|
|
227
|
+
const bar = this.bars[0];
|
|
228
|
+
const fill = bar.querySelector(".fort-bar__fill");
|
|
229
|
+
const filled = total - unfilled;
|
|
230
|
+
const percent = total === 0 ? 0 : (filled / total) * 100;
|
|
231
|
+
|
|
232
|
+
bar.style.width = `${percent}%`;
|
|
233
|
+
|
|
234
|
+
if (colors.length === 0) {
|
|
235
|
+
fill.style.background = this._colorValue();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const index = Math.max(0, Math.min(colors.length - 1, unfilled - 1));
|
|
240
|
+
fill.style.background = colors[index] || colors[0];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
_applyMerge(percent) {
|
|
244
|
+
const color = this._colorValue();
|
|
245
|
+
const half = percent / 2;
|
|
246
|
+
|
|
247
|
+
this.bars.forEach((bar) => {
|
|
248
|
+
bar.style.width = `${half}%`;
|
|
249
|
+
const fill = bar.querySelector(".fort-bar__fill");
|
|
250
|
+
fill.style.background = color;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_colorValue() {
|
|
255
|
+
const value = this.config.value;
|
|
256
|
+
|
|
257
|
+
if (Array.isArray(value)) {
|
|
258
|
+
return value[0] || "#009DFF";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return value || "#009DFF";
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
_colorArray() {
|
|
265
|
+
const value = this.config.value;
|
|
266
|
+
|
|
267
|
+
if (Array.isArray(value)) {
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return [value || "#009DFF"];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Export for tests and module loaders; global for Sprockets.
|
|
276
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
277
|
+
module.exports = FortProgress;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
window.FortProgress = FortProgress;
|
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
//= require fort
|
|
2
|
+
|
|
3
|
+
(function () {
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
<% path_to_file = Rails.root.join("config/fort.yml").to_s %>
|
|
7
|
+
<% fortconfig = File.exist?(path_to_file) ? YAML.load_file(path_to_file) : { "type" => "solid", "value" => "#009DFF" } %>
|
|
8
|
+
|
|
9
|
+
var config = <%= JSON.dump(fortconfig) %>;
|
|
10
|
+
|
|
11
|
+
if (config.type == null) {
|
|
12
|
+
config.type = "solid";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function startFort() {
|
|
16
|
+
if (window._railsFortInstance) {
|
|
17
|
+
window._railsFortInstance.destroy();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
window._railsFortInstance = new FortProgress(config);
|
|
21
|
+
window._railsFortInstance.init();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (document.readyState === "loading") {
|
|
25
|
+
document.addEventListener("DOMContentLoaded", startFort);
|
|
26
|
+
} else {
|
|
27
|
+
startFort();
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Rails-Fort progress bar styles
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.fort-bar,
|
|
6
|
+
.top-one {
|
|
7
|
+
background: #009dff;
|
|
8
|
+
position: fixed;
|
|
9
|
+
z-index: 1031;
|
|
10
|
+
left: 0;
|
|
11
|
+
height: 4px;
|
|
12
|
+
width: 0;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
transition: width 1s ease, background 0.3s ease;
|
|
15
|
+
top: 0;
|
|
16
|
+
bottom: auto;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.fort-bar--secondary,
|
|
20
|
+
.top-two {
|
|
21
|
+
background: #009dff;
|
|
22
|
+
position: fixed;
|
|
23
|
+
z-index: 1031;
|
|
24
|
+
right: 0;
|
|
25
|
+
left: auto;
|
|
26
|
+
transform: scaleX(-1);
|
|
27
|
+
height: 4px;
|
|
28
|
+
width: 0;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
transition: width 1s ease, background 0.3s ease;
|
|
31
|
+
top: 0;
|
|
32
|
+
bottom: auto;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.fort-bar--bottom,
|
|
36
|
+
.top-one.fort-bar--bottom,
|
|
37
|
+
.top-two.fort-bar--bottom {
|
|
38
|
+
top: auto;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.fort-bar__fill,
|
|
43
|
+
.top-one .colors,
|
|
44
|
+
.top-two .colors {
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.fort-form,
|
|
50
|
+
.form {
|
|
51
|
+
/* wrapper for forms; no extra layout rules required */
|
|
52
|
+
}
|
data/lib/rails/fort/version.rb
CHANGED
data/lib/rails/fort.rb
CHANGED
data/rails-fort.gemspec
CHANGED
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
require 'rails/fort/version'
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/rails/fort/version"
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |spec|
|
|
7
6
|
spec.name = "rails-fort"
|
|
8
7
|
spec.version = Rails::Fort::VERSION
|
|
9
|
-
spec.authors = ["
|
|
8
|
+
spec.authors = ["ethi"]
|
|
10
9
|
spec.email = ["ethirajsrinivasan@gmail.com"]
|
|
11
10
|
|
|
12
11
|
spec.summary = "Modern progress bar for form completion"
|
|
13
|
-
spec.description = "
|
|
12
|
+
spec.description = "Rails-Fort provides a modern, animated progress bar for form completion tracking. It automatically detects form fields and displays visual progress as users fill out forms, with multiple customizable effect types including solid, gradient, sections, flash, and merge animations."
|
|
14
13
|
spec.homepage = "https://github.com/ethirajsrinivasan/rails-fort"
|
|
15
14
|
spec.license = "MIT"
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
spec.metadata = {
|
|
17
|
+
"allowed_push_host" => "https://rubygems.org",
|
|
18
|
+
"homepage_uri" => spec.homepage,
|
|
19
|
+
"source_code_uri" => "https://github.com/ethirajsrinivasan/rails-fort",
|
|
20
|
+
"bug_tracker_uri" => "https://github.com/ethirajsrinivasan/rails-fort/issues",
|
|
21
|
+
"changelog_uri" => "https://github.com/ethirajsrinivasan/rails-fort/blob/master/CHANGELOG.md",
|
|
22
|
+
"documentation_uri" => "https://github.com/ethirajsrinivasan/rails-fort/blob/master/README.md",
|
|
23
|
+
"rubygems_mfa_required" => "true"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
spec.files = Dir.chdir(__dir__) do
|
|
27
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
23
28
|
end
|
|
24
29
|
|
|
25
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
30
|
spec.bindir = "exe"
|
|
27
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
32
|
spec.require_paths = ["lib"]
|
|
29
|
-
|
|
30
|
-
spec.
|
|
31
|
-
|
|
32
|
-
spec.
|
|
33
|
+
|
|
34
|
+
spec.required_ruby_version = ">= 3.0"
|
|
35
|
+
|
|
36
|
+
spec.add_runtime_dependency "railties", ">= 6.0", "< 9.0"
|
|
37
|
+
|
|
38
|
+
spec.add_development_dependency "bundler", "~> 2.4"
|
|
39
|
+
spec.add_development_dependency "bundler-audit", "~> 0.9"
|
|
40
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
41
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
|
42
|
+
spec.add_development_dependency "rubocop", "~> 1.50"
|
|
33
43
|
end
|
metadata
CHANGED
|
@@ -1,86 +1,144 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-fort
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
autorequire:
|
|
7
|
+
- ethi
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: railties
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '6.0'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '6.0'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9.0'
|
|
13
32
|
- !ruby/object:Gem::Dependency
|
|
14
33
|
name: bundler
|
|
15
34
|
requirement: !ruby/object:Gem::Requirement
|
|
16
35
|
requirements:
|
|
17
36
|
- - "~>"
|
|
18
37
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
38
|
+
version: '2.4'
|
|
39
|
+
type: :development
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '2.4'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: bundler-audit
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - "~>"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0.9'
|
|
20
53
|
type: :development
|
|
21
54
|
prerelease: false
|
|
22
55
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
56
|
requirements:
|
|
24
57
|
- - "~>"
|
|
25
58
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
59
|
+
version: '0.9'
|
|
27
60
|
- !ruby/object:Gem::Dependency
|
|
28
61
|
name: rake
|
|
29
62
|
requirement: !ruby/object:Gem::Requirement
|
|
30
63
|
requirements:
|
|
31
64
|
- - "~>"
|
|
32
65
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
66
|
+
version: '13.0'
|
|
34
67
|
type: :development
|
|
35
68
|
prerelease: false
|
|
36
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
70
|
requirements:
|
|
38
71
|
- - "~>"
|
|
39
72
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
73
|
+
version: '13.0'
|
|
41
74
|
- !ruby/object:Gem::Dependency
|
|
42
75
|
name: rspec
|
|
43
76
|
requirement: !ruby/object:Gem::Requirement
|
|
44
77
|
requirements:
|
|
45
|
-
- - "
|
|
78
|
+
- - "~>"
|
|
46
79
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
80
|
+
version: '3.12'
|
|
48
81
|
type: :development
|
|
49
82
|
prerelease: false
|
|
50
83
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
84
|
requirements:
|
|
52
|
-
- - "
|
|
85
|
+
- - "~>"
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '3.12'
|
|
88
|
+
- !ruby/object:Gem::Dependency
|
|
89
|
+
name: rubocop
|
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - "~>"
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '1.50'
|
|
95
|
+
type: :development
|
|
96
|
+
prerelease: false
|
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - "~>"
|
|
53
100
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
55
|
-
description:
|
|
101
|
+
version: '1.50'
|
|
102
|
+
description: Rails-Fort provides a modern, animated progress bar for form completion
|
|
103
|
+
tracking. It automatically detects form fields and displays visual progress as users
|
|
104
|
+
fill out forms, with multiple customizable effect types including solid, gradient,
|
|
105
|
+
sections, flash, and merge animations.
|
|
56
106
|
email:
|
|
57
107
|
- ethirajsrinivasan@gmail.com
|
|
58
108
|
executables: []
|
|
59
109
|
extensions: []
|
|
60
110
|
extra_rdoc_files: []
|
|
61
111
|
files:
|
|
112
|
+
- ".github/workflows/ci.yml"
|
|
62
113
|
- ".gitignore"
|
|
63
|
-
- ".
|
|
114
|
+
- ".rspec"
|
|
115
|
+
- ".rubocop.yml"
|
|
116
|
+
- CHANGELOG.md
|
|
64
117
|
- CODE_OF_CONDUCT.md
|
|
65
118
|
- Gemfile
|
|
66
119
|
- LICENSE.txt
|
|
67
120
|
- README.md
|
|
68
121
|
- Rakefile
|
|
122
|
+
- UPGRADE_GUIDE.md
|
|
123
|
+
- app/assets/javascripts/fort.js
|
|
69
124
|
- app/assets/javascripts/rails_fort.js.erb
|
|
125
|
+
- app/assets/stylesheets/fort.css
|
|
70
126
|
- bin/console
|
|
71
127
|
- bin/setup
|
|
72
128
|
- lib/rails/fort.rb
|
|
73
129
|
- lib/rails/fort/version.rb
|
|
74
|
-
- npm-debug.log
|
|
75
130
|
- rails-fort.gemspec
|
|
76
|
-
- vendor/assets/javascripts/fort.min.js
|
|
77
|
-
- vendor/assets/stylesheets/fort.min.css
|
|
78
131
|
homepage: https://github.com/ethirajsrinivasan/rails-fort
|
|
79
132
|
licenses:
|
|
80
133
|
- MIT
|
|
81
134
|
metadata:
|
|
82
135
|
allowed_push_host: https://rubygems.org
|
|
83
|
-
|
|
136
|
+
homepage_uri: https://github.com/ethirajsrinivasan/rails-fort
|
|
137
|
+
source_code_uri: https://github.com/ethirajsrinivasan/rails-fort
|
|
138
|
+
bug_tracker_uri: https://github.com/ethirajsrinivasan/rails-fort/issues
|
|
139
|
+
changelog_uri: https://github.com/ethirajsrinivasan/rails-fort/blob/master/CHANGELOG.md
|
|
140
|
+
documentation_uri: https://github.com/ethirajsrinivasan/rails-fort/blob/master/README.md
|
|
141
|
+
rubygems_mfa_required: 'true'
|
|
84
142
|
rdoc_options: []
|
|
85
143
|
require_paths:
|
|
86
144
|
- lib
|
|
@@ -88,16 +146,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
88
146
|
requirements:
|
|
89
147
|
- - ">="
|
|
90
148
|
- !ruby/object:Gem::Version
|
|
91
|
-
version:
|
|
149
|
+
version: '3.0'
|
|
92
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
151
|
requirements:
|
|
94
152
|
- - ">="
|
|
95
153
|
- !ruby/object:Gem::Version
|
|
96
154
|
version: '0'
|
|
97
155
|
requirements: []
|
|
98
|
-
|
|
99
|
-
rubygems_version: 2.5.1
|
|
100
|
-
signing_key:
|
|
156
|
+
rubygems_version: 3.6.7
|
|
101
157
|
specification_version: 4
|
|
102
158
|
summary: Modern progress bar for form completion
|
|
103
159
|
test_files: []
|
data/.travis.yml
DELETED
data/npm-debug.log
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
0 info it worked if it ends with ok
|
|
2
|
-
1 verbose cli [ '/usr/bin/nodejs', '/usr/bin/npm', 'completion' ]
|
|
3
|
-
2 info using npm@1.3.10
|
|
4
|
-
3 info using node@v0.10.25
|
|
5
|
-
4 error Error: ENOENT, open '/usr/share/npm/lib/utils/completion.sh'
|
|
6
|
-
5 error If you need help, you may report this log at:
|
|
7
|
-
5 error <http://github.com/isaacs/npm/issues>
|
|
8
|
-
5 error or email it to:
|
|
9
|
-
5 error <npm-@googlegroups.com>
|
|
10
|
-
6 error System Linux 3.19.0-25-generic
|
|
11
|
-
7 error command "/usr/bin/nodejs" "/usr/bin/npm" "completion"
|
|
12
|
-
8 error cwd /home/ethi/apps/gems/rails-fort
|
|
13
|
-
9 error node -v v0.10.25
|
|
14
|
-
10 error npm -v 1.3.10
|
|
15
|
-
11 error path /usr/share/npm/lib/utils/completion.sh
|
|
16
|
-
12 error code ENOENT
|
|
17
|
-
13 error errno 34
|
|
18
|
-
14 verbose exit [ 34, true ]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var Fort={clean:function(){for(var e=document.querySelectorAll(".form"),t=e.length;t--;){var o=e[t].querySelectorAll("input, textarea, select");Array.prototype.forEach.call(o,function(e){0!=e.value.length&&(e.classList?e.classList.add("ignore"):e.className+=" ignore")});var n=e[t].querySelectorAll("input[type=hidden]");Array.prototype.forEach.call(n,function(e){e.classList?e.classList.add("ignore"):e.className+=" ignore"})}},solid:function(e){function t(t){for(var o=[],r=n.length;r--;)n[r].value.length||o.push(n[r]);for(var l=o.length,s=n.length,a=document.querySelectorAll(".top-one"),i=a.length;i--;)a[i].style.width=100-l/s*100+"%";document.getElementById("top1").style.background=e}Fort.clean(),document.body.innerHTML='<div class="top-one" id="top1"><div class="colors"></div></div>'+document.body.innerHTML;for(var o=document.querySelectorAll(".form"),n=[],r=o.length;r--;)for(var l=o[r].querySelectorAll("input, textarea, select"),s=l.length;s--;){classes=l[s].className.replace(/\s+/g," ").split(" "),ignore=!1;for(var a=classes.length;a--;)if("ignore"==classes[a]){ignore=!0;break}"button"==l[s].type||"submit"==l[s].type||ignore||(n.push(l[s]),l[s].addEventListener("input",t,!1))}},gradient:function(e,t){function o(o){for(var n=[],l=r.length;l--;)r[l].value.length||n.push(r[l]);for(var s=n.length,a=r.length,i=document.querySelectorAll(".top-one"),c=i.length;c--;)i[c].style.width=100-s/a*100+"%";orientation="to right";var u="linear-gradient("+orientation+", "+e+", "+t+")";document.getElementById("top1").style.background=u}Fort.clean(),document.body.innerHTML='<div class="top-one" id="top1"><div class="colors"></div></div>'+document.body.innerHTML;for(var n=document.querySelectorAll(".form"),r=[],l=n.length;l--;)for(var s=n[l].querySelectorAll("input, textarea, select"),a=s.length;a--;){classes=s[a].className.replace(/\s+/g," ").split(" "),ignore=!1;for(var i=classes.length;i--;)if("ignore"==classes[i]){ignore=!0;break}"button"==s[a].type||"submit"==s[a].type||ignore||(r.push(s[a]),s[a].addEventListener("input",o,!1))}},sections:function(){function e(e){for(var t=[],o=s.length;o--;)s[o].value.length||t.push(s[o]);for(var n=t.length,r=s.length,l=document.querySelectorAll(".top-one"),a=l.length;a--;)l[a].style.width=100-n/r*100+"%"}function t(e){var t=[],o=0;for(n=0;n<2*e.length;n++){n%2&&o++;var r=Math.floor(1e3*o/e.length)/10;t.push([e[n-o],r+"%"])}return t}function o(e){var t,o=e.length;for(t=0;o>t;t++)e[t]=e[t].join(" ");return"linear-gradient( to right, "+e.join(", ")+")"}Fort.clean();for(var n=0;n<arguments.length;++n)var r=Array.prototype.slice.call(arguments);document.body.innerHTML='<div class="top-one" id="top1"><div class="colors"></div></div>'+document.body.innerHTML;for(var l=document.querySelectorAll(".form"),s=[],n=l.length;n--;)for(var a=l[n].querySelectorAll("input, textarea, select"),i=a.length;i--;){classes=a[i].className.replace(/\s+/g," ").split(" "),ignore=!1;for(var c=classes.length;c--;)if("ignore"==classes[c]){ignore=!0;break}"button"==a[i].type||"submit"==a[i].type||ignore||(s.push(a[i]),a[i].addEventListener("input",e,!1))}document.getElementsByClassName("top-one").innerHTML='<div class="colors"></div>',document.querySelector(".colors").style.background=o(t(r.sort()));var u=window.innerWidth+"px";document.querySelector(".colors").style.width=u},flash:function(){function e(e){for(var t=[],o=l.length;o--;)l[o].value.length||t.push(l[o]);for(var r=t.length,s=l.length,a=document.querySelectorAll(".top-one"),i=a.length;i--;)a[i].style.width=100-r/s*100+"%",a[i].style.background=n[s-r-1]}Fort.clean();for(var t=0;t<arguments.length;++t){arguments.length,arguments[t]}var o=Array.prototype.slice.call(arguments),n=o.sort();document.body.innerHTML='<div class="top-one" id="top1"><div class="colors"></div></div>'+document.body.innerHTML;for(var r=document.querySelectorAll(".form"),l=[],t=r.length;t--;)for(var s=r[t].querySelectorAll("input, textarea, select"),a=s.length;a--;){classes=s[a].className.replace(/\s+/g," ").split(" "),ignore=!1;for(var i=classes.length;i--;)if("ignore"==classes[i]){ignore=!0;break}"button"==s[a].type||"submit"==s[a].type||ignore||(l.push(s[a]),s[a].addEventListener("input",e,!1))}},merge:function(e){function t(t){for(var o=[],r=n.length;r--;)n[r].value.length||o.push(n[r]);for(var l=o.length,s=n.length,a=document.querySelectorAll("#top1"),i=a.length;i--;){precalct=100-l/s*100;var c=precalct/2;a[i].style.width=c+"%"}for(var l=o.length,s=n.length,a=document.querySelectorAll("#top2"),i=a.length;i--;){precalct=100-l/s*100;var c=precalct/2;a[i].style.width=c+"%"}document.getElementById("top1").style.background=e,document.getElementById("top2").style.background=e}Fort.clean(),document.body.innerHTML='<div class="top-one" id="top1"><div class="colors"></div></div>'+document.body.innerHTML,document.body.innerHTML='<div class="top-two" id="top2"><div class="colors"></div></div>'+document.body.innerHTML;for(var o=document.querySelectorAll(".form"),n=[],r=o.length;r--;)for(var l=o[r].querySelectorAll("input, textarea, select"),s=l.length;s--;){classes=l[s].className.replace(/\s+/g," ").split(" "),ignore=!1;for(var a=classes.length;a--;)if("ignore"==classes[a]){ignore=!0;break}"button"==l[s].type||"submit"==l[s].type||ignore||(n.push(l[s]),l[s].addEventListener("input",t,!1))}},config:function(e){var t=document.querySelector("#top1"),o=document.querySelector("#top2")||{style:{}};e.height&&(t.style.height=e.height,o.style.height=e.height),e.alignment&&("top"===e.alignment?(t.style.top=0,t.style.bottom="auto",o.style.top=0,o.style.bottom="auto"):(t.style.top="auto",t.style.bottom=0,o.style.top="auto",o.style.bottom=0)),e.duration&&(t.style.transitionDuration=e.duration,o.style.transitionDuration=e.duration)}};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.top-one{background:#009dff;position:fixed;z-index:1031;top:0;left:0;height:4px;transition:all 1s;width:0;overflow:hidden}.top-two{background:#009dff;position:fixed;z-index:1031;top:0;right:0;transform:rotate(180deg);height:4px;transition:all 1s;width:0;overflow:hidden}.colors{width:100%;height:4px}
|