recurring_select_fix_v1_2_0 1.2.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +140 -0
- data/Rakefile +24 -0
- data/app/assets/images/recurring_select/cancel.png +0 -0
- data/app/assets/images/recurring_select/throbber_13x13.gif +0 -0
- data/app/assets/javascripts/jquery-mobile-rs.js.coffee +15 -0
- data/app/assets/javascripts/recurring_select.js.coffee +98 -0
- data/app/assets/javascripts/recurring_select/fr.js.coffee +23 -0
- data/app/assets/javascripts/recurring_select_dialog.js.coffee.erb +371 -0
- data/app/assets/stylesheets/jquery-mobile-rs.css.scss.erb +33 -0
- data/app/assets/stylesheets/recurring_select.css.scss.erb +101 -0
- data/app/assets/stylesheets/utilities.scss +26 -0
- data/app/helpers/recurring_select_helper.rb +27 -0
- data/app/helpers/utilities/form_options_ext.rb +64 -0
- data/app/helpers/utilities/tag_ext.rb +53 -0
- data/app/middleware/recurring_select_middleware.rb +26 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/fr.yml +8 -0
- data/config/routes.rb +2 -0
- data/lib/recurring_select.rb +82 -0
- data/lib/recurring_select/engine.rb +16 -0
- data/lib/recurring_select/version.rb +3 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9d891f78c076eee623313f89e37973c28611e0ce5fe3f5e1d65dc3f51696543e
|
4
|
+
data.tar.gz: 2ca75833158a39b737f05fdaed2c3e6fdb9ca7da9e523bdaac58976fb23a7093
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6861193556c1919f710b72cb2441a8138da88e22b34184edd9dd9efacf8a02af0ade192e3f489ea5ef3302603985b7569b1e1e102661870aa97bf78e05f23cfe
|
7
|
+
data.tar.gz: f612ae4d3e962b318f3f38aa7cfe727489a61cddf10ce96f6c9d6c2817b7101f0385935ef6d50fbcaa6a831a442e18412b09dd2d36aaeea633a3f6571861b685
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Jobber (OctopusApp Inc)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
RecurringSelect
|
2
|
+
=============
|
3
|
+
|
4
|
+
[](https://travis-ci.org/GetJobber/recurring_select) [](https://codeclimate.com/github/GetJobber/recurring_select)
|
5
|
+
|
6
|
+
This is a gem to add a number of selectors and helpers for working with recurring schedules in a rails app.
|
7
|
+
It uses the [IceCube](https://github.com/seejohnrun/ice_cube) recurring scheduling gem.
|
8
|
+
|
9
|
+
Created by the [Jobber](http://getjobber.com) team for Jobber, the leading business management tool for field service companies.
|
10
|
+
|
11
|
+
Check out the [live demo](http://recurring-select-demo.herokuapp.com/) (code in [spec\dummy](https://github.com/GetJobber/recurring_select/tree/master/spec/dummy) folder)
|
12
|
+
|
13
|
+
|
14
|
+
Usage
|
15
|
+
-----
|
16
|
+
|
17
|
+
Basic selector:
|
18
|
+
|
19
|
+
Load the gem:
|
20
|
+
`gem 'recurring_select`
|
21
|
+
|
22
|
+
Require assets
|
23
|
+
Desktop view
|
24
|
+
application.js
|
25
|
+
`//= require recurring_select`
|
26
|
+
application.css
|
27
|
+
`//= require recurring_select`
|
28
|
+
|
29
|
+
or jQueryMobile interface
|
30
|
+
application.js
|
31
|
+
`//= require jquery-mobile-rs`
|
32
|
+
application.css
|
33
|
+
`//= require jquery-mobile-rs`
|
34
|
+
|
35
|
+
|
36
|
+
In the form view call the helper:
|
37
|
+
`<%= f.select_recurring :recurring_rule_column %>`
|
38
|
+
|
39
|
+
Options
|
40
|
+
-------
|
41
|
+
|
42
|
+
Defaults Values
|
43
|
+
```
|
44
|
+
f.select_recurring :current_existing_rule, [
|
45
|
+
IceCube::Rule.weekly.day(:monday, :wednesday, :friday),
|
46
|
+
IceCube::Rule.monthly.day_of_month(-1)
|
47
|
+
]
|
48
|
+
```
|
49
|
+
|
50
|
+
:allow_blank let's you pick if there is a "not recurring" value
|
51
|
+
```
|
52
|
+
f.select_recurring :current_existing_rule, :allow_blank => true
|
53
|
+
```
|
54
|
+
|
55
|
+
|
56
|
+
Additional Helpers
|
57
|
+
------------------
|
58
|
+
|
59
|
+
RecurringSelect also comes with several helpers for parsing up the
|
60
|
+
parameters when they hit your application.
|
61
|
+
|
62
|
+
You can send the column into the `is_valid_rule?` method to check the
|
63
|
+
validity of the input.
|
64
|
+
`RecurringSelect.is_valid_rule?(possible_rule)`
|
65
|
+
|
66
|
+
There is also a `dirty_hash_to_rule` method for sanitizing the inputs
|
67
|
+
for IceCube. This is sometimes needed based on if you're receiving strings, fixed
|
68
|
+
numbers, strings vs symbols, etc.
|
69
|
+
`RecurringSelect.dirty_hash_to_rule(params)`
|
70
|
+
|
71
|
+
I18n
|
72
|
+
----
|
73
|
+
Recurrent select is I18n aware
|
74
|
+
|
75
|
+
You can create a locale file like this:
|
76
|
+
|
77
|
+
```
|
78
|
+
en:
|
79
|
+
recurring_select:
|
80
|
+
not_recurring: "- not recurring -"
|
81
|
+
change_schedule: "Change schedule..."
|
82
|
+
set_schedule: "Set schedule..."
|
83
|
+
new_custom_schedule: "New custom schedule..."
|
84
|
+
custom_schedule: "Custom schedule..."
|
85
|
+
or: or
|
86
|
+
```
|
87
|
+
|
88
|
+
You have to translate javascript texts too by including the locale file in your assets manifest. Only french and english are supported for the moment
|
89
|
+
|
90
|
+
```
|
91
|
+
//= require recurring_select/en
|
92
|
+
//= require recurring_select/fr
|
93
|
+
```
|
94
|
+
|
95
|
+
For other languages include a file like this:
|
96
|
+
|
97
|
+
```
|
98
|
+
$.fn.recurring_select.texts = {
|
99
|
+
repeat: "Repeat"
|
100
|
+
frequency: "Frequency"
|
101
|
+
daily: "Daily"
|
102
|
+
weekly: "Weekly"
|
103
|
+
monthly: "Monthly"
|
104
|
+
yearly: "Yearly"
|
105
|
+
every: "Every"
|
106
|
+
days: "day(s)"
|
107
|
+
weeks_on: "week(s) on"
|
108
|
+
months: "month(s)"
|
109
|
+
years: "year(s)"
|
110
|
+
first_day_of_week: 1
|
111
|
+
day_of_month: "Day of month"
|
112
|
+
day_of_week: "Day of week"
|
113
|
+
cancel: "Cancel"
|
114
|
+
ok: "OK"
|
115
|
+
days_first_letter: ["S", "M", "T", "W", "T", "F", "S" ]
|
116
|
+
order: ["1st", "2nd", "3rd", "4th"]
|
117
|
+
}
|
118
|
+
```
|
119
|
+
|
120
|
+
Testing and development
|
121
|
+
----------------------
|
122
|
+
|
123
|
+
Start the dummy server for clicking around the interface:
|
124
|
+
`rails s`
|
125
|
+
|
126
|
+
Use [Guard](https://github.com/guard/guard) and RSpec for all tests. I'd
|
127
|
+
love to get jasmine running also, but haven't had time yet.
|
128
|
+
|
129
|
+
Tests can be ran against different versions of Rails like so:
|
130
|
+
|
131
|
+
```
|
132
|
+
rake appraisal:install
|
133
|
+
rake appraisal
|
134
|
+
```
|
135
|
+
|
136
|
+
Feel free to open issues or send pull requests.
|
137
|
+
|
138
|
+
Licensing
|
139
|
+
---------
|
140
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'appraisal'
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
require 'rubygems/package_task'
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
require 'rdoc/task'
|
14
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'RecurringSelect'
|
17
|
+
rdoc.options << '--line-numbers'
|
18
|
+
rdoc.rdoc_files.include('README.rdoc')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
22
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
23
|
+
load 'rails/tasks/engine.rake'
|
24
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
//= require recurring_select
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
$ ->
|
5
|
+
$(document).on "recurring_select:cancel recurring_select:save", ".recurring_select", ->
|
6
|
+
$(this).selectmenu('refresh')
|
7
|
+
|
8
|
+
$(document).on "recurring_select:dialog_opened", ".rs_dialog_holder", ->
|
9
|
+
$(this).find("select").attr("data-theme", $('.recurring_select').data("theme")).attr("data-mini", true).selectmenu()
|
10
|
+
$(this).find("input[type=text]").textinput()
|
11
|
+
|
12
|
+
$(this).on "recurring_select:dialog_positioned", ".rs_dialog", ->
|
13
|
+
$(this).css
|
14
|
+
"top" : $(window).scrollTop()+"px"
|
15
|
+
|
@@ -0,0 +1,98 @@
|
|
1
|
+
//= require recurring_select_dialog
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
$ = jQuery
|
5
|
+
$ ->
|
6
|
+
$(document).on "focus", ".recurring_select", ->
|
7
|
+
$(this).recurring_select('set_initial_values')
|
8
|
+
|
9
|
+
$(document).on "change", ".recurring_select", ->
|
10
|
+
$(this).recurring_select('changed')
|
11
|
+
|
12
|
+
methods =
|
13
|
+
set_initial_values: ->
|
14
|
+
@data 'initial-value-hash', @val()
|
15
|
+
@data 'initial-value-str', $(@find("option").get()[@.prop("selectedIndex")]).text()
|
16
|
+
|
17
|
+
changed: ->
|
18
|
+
if @val() == "custom"
|
19
|
+
methods.open_custom.apply(@)
|
20
|
+
else
|
21
|
+
methods.set_initial_values.apply(@)
|
22
|
+
|
23
|
+
open_custom: ->
|
24
|
+
@data "recurring-select-active", true
|
25
|
+
new RecurringSelectDialog(@)
|
26
|
+
@blur()
|
27
|
+
|
28
|
+
save: (new_rule) ->
|
29
|
+
@find("option[data-custom]").remove()
|
30
|
+
new_json_val = JSON.stringify(new_rule.hash)
|
31
|
+
|
32
|
+
# TODO: check for matching name, and replace that value if found
|
33
|
+
|
34
|
+
if $.inArray(new_json_val, @find("option").map -> $(@).val()) == -1
|
35
|
+
methods.insert_option.apply @, [new_rule.str, new_json_val]
|
36
|
+
|
37
|
+
@val new_json_val
|
38
|
+
methods.set_initial_values.apply @
|
39
|
+
@.trigger "recurring_select:save"
|
40
|
+
|
41
|
+
current_rule: ->
|
42
|
+
str: @data("initial-value-str")
|
43
|
+
hash: $.parseJSON(@data("initial-value-hash"))
|
44
|
+
|
45
|
+
cancel: ->
|
46
|
+
@val @data("initial-value-hash")
|
47
|
+
@data "recurring-select-active", false
|
48
|
+
@.trigger "recurring_select:cancel"
|
49
|
+
|
50
|
+
|
51
|
+
insert_option: (new_rule_str, new_rule_json) ->
|
52
|
+
separator = @find("option:disabled")
|
53
|
+
if separator.length == 0
|
54
|
+
separator = @find("option")
|
55
|
+
separator = separator.last()
|
56
|
+
|
57
|
+
new_option = $(document.createElement("option"))
|
58
|
+
new_option.attr "data-custom", true
|
59
|
+
|
60
|
+
if new_rule_str.substr(new_rule_str.length - 1) != "*"
|
61
|
+
new_rule_str+="*"
|
62
|
+
|
63
|
+
new_option.text new_rule_str
|
64
|
+
new_option.val new_rule_json
|
65
|
+
new_option.insertBefore separator
|
66
|
+
|
67
|
+
methods: ->
|
68
|
+
methods
|
69
|
+
|
70
|
+
$.fn.recurring_select = (method) ->
|
71
|
+
if method of methods
|
72
|
+
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
|
73
|
+
else
|
74
|
+
$.error( "Method #{method} does not exist on jQuery.recurring_select" );
|
75
|
+
|
76
|
+
$.fn.recurring_select.texts = {
|
77
|
+
repeat: "Repeat"
|
78
|
+
last_day: "Last Day"
|
79
|
+
frequency: "Frequency"
|
80
|
+
daily: "Daily"
|
81
|
+
weekly: "Weekly"
|
82
|
+
monthly: "Monthly"
|
83
|
+
yearly: "Yearly"
|
84
|
+
every: "Every"
|
85
|
+
days: "day(s)"
|
86
|
+
weeks_on: "week(s) on"
|
87
|
+
months: "month(s)"
|
88
|
+
years: "year(s)"
|
89
|
+
first_day_of_week: 1
|
90
|
+
day_of_month: "Day of month"
|
91
|
+
day_of_week: "Day of week"
|
92
|
+
cancel: "Cancel"
|
93
|
+
ok: "OK"
|
94
|
+
summary: "Summary"
|
95
|
+
first_day_of_week: 0
|
96
|
+
days_first_letter: ["S", "M", "T", "W", "T", "F", "S" ]
|
97
|
+
order: ["1st", "2nd", "3rd", "4th"]
|
98
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$.fn.recurring_select.texts = {
|
2
|
+
repeat: "Récurrence"
|
3
|
+
last_day: "Dernier jour"
|
4
|
+
frequency: "Fréquence"
|
5
|
+
daily: "Tous les jours"
|
6
|
+
weekly: "Toutes les semaines"
|
7
|
+
monthly: "Tous les mois"
|
8
|
+
yearly: "Tous les ans"
|
9
|
+
every: "Tous les"
|
10
|
+
days: "jour(s)"
|
11
|
+
weeks_on: "semaine(s) le"
|
12
|
+
months: "mois"
|
13
|
+
years: "année(s)"
|
14
|
+
cancel: "Annuler"
|
15
|
+
day_of_month: "Jour du mois"
|
16
|
+
day_of_week: "Jour de la semaine"
|
17
|
+
ok: "OK"
|
18
|
+
cancel: "Annuler"
|
19
|
+
summary: "Résumé"
|
20
|
+
first_day_of_week: 1
|
21
|
+
days_first_letter: ["D", "L", "M", "M", "J", "V", "S" ]
|
22
|
+
order: ["1er", "2ème", "3ème", "4ème"]
|
23
|
+
}
|
@@ -0,0 +1,371 @@
|
|
1
|
+
window.RecurringSelectDialog =
|
2
|
+
class RecurringSelectDialog
|
3
|
+
constructor: (@recurring_selector) ->
|
4
|
+
@current_rule = @recurring_selector.recurring_select('current_rule')
|
5
|
+
@initDialogBox()
|
6
|
+
if not @current_rule.hash? or not @current_rule.hash.rule_type?
|
7
|
+
@freqChanged()
|
8
|
+
else
|
9
|
+
setTimeout @positionDialogVert, 10 # allow initial render
|
10
|
+
|
11
|
+
initDialogBox: ->
|
12
|
+
$(".rs_dialog_holder").remove()
|
13
|
+
|
14
|
+
open_in = $("body")
|
15
|
+
open_in = $(".ui-page-active") if $(".ui-page-active").length
|
16
|
+
open_in.append @template()
|
17
|
+
@outer_holder = $(".rs_dialog_holder")
|
18
|
+
@inner_holder = @outer_holder.find ".rs_dialog"
|
19
|
+
@content = @outer_holder.find ".rs_dialog_content"
|
20
|
+
@positionDialogVert(true)
|
21
|
+
@mainEventInit()
|
22
|
+
@freqInit()
|
23
|
+
@summaryInit()
|
24
|
+
@freq_select.focus()
|
25
|
+
@outer_holder.trigger "recurring_select:dialog_opened"
|
26
|
+
|
27
|
+
positionDialogVert: (initial_positioning) =>
|
28
|
+
window_height = $(window).height()
|
29
|
+
window_width = $(window).width()
|
30
|
+
dialog_height = @content.outerHeight()
|
31
|
+
if dialog_height < 80
|
32
|
+
dialog_height = 80
|
33
|
+
margin_top = (window_height - dialog_height)/2 - 30
|
34
|
+
margin_top = 10 if margin_top < 10
|
35
|
+
# if dialog_height > window_height - 20
|
36
|
+
# dialog_height = window_height - 20
|
37
|
+
|
38
|
+
new_style_hash =
|
39
|
+
"margin-top" : margin_top+"px"
|
40
|
+
"min-height" : dialog_height+"px"
|
41
|
+
|
42
|
+
if initial_positioning?
|
43
|
+
@inner_holder.css new_style_hash
|
44
|
+
@inner_holder.trigger "recurring_select:dialog_positioned"
|
45
|
+
else
|
46
|
+
@content.css {"width": @content.width()+"px"}
|
47
|
+
@inner_holder.addClass "animated"
|
48
|
+
@inner_holder.animate new_style_hash, 200, =>
|
49
|
+
@inner_holder.removeClass "animated"
|
50
|
+
@content.css {"width": "auto"}
|
51
|
+
@inner_holder.trigger "recurring_select:dialog_positioned"
|
52
|
+
|
53
|
+
cancel: =>
|
54
|
+
@outer_holder.remove()
|
55
|
+
@recurring_selector.recurring_select('cancel')
|
56
|
+
|
57
|
+
outerCancel: (event) =>
|
58
|
+
if $(event.target).hasClass("rs_dialog_holder")
|
59
|
+
@cancel()
|
60
|
+
|
61
|
+
save: =>
|
62
|
+
return if !@current_rule.str?
|
63
|
+
@outer_holder.remove()
|
64
|
+
@recurring_selector.recurring_select('save', @current_rule)
|
65
|
+
|
66
|
+
# ========================= Init Methods ===============================
|
67
|
+
|
68
|
+
mainEventInit: ->
|
69
|
+
# Tap hooks are for jQueryMobile
|
70
|
+
@outer_holder.on 'click tap', @outerCancel
|
71
|
+
@content.on 'click tap', 'h1 a', @cancel
|
72
|
+
@save_button = @content.find('input.rs_save').on "click tap", @save
|
73
|
+
@content.find('input.rs_cancel').on "click tap", @cancel
|
74
|
+
|
75
|
+
freqInit: ->
|
76
|
+
@freq_select = @outer_holder.find ".rs_frequency"
|
77
|
+
if @current_rule.hash? && (rule_type = @current_rule.hash.rule_type)?
|
78
|
+
if rule_type.search(/Weekly/) != -1
|
79
|
+
@freq_select.prop('selectedIndex', 1)
|
80
|
+
@initWeeklyOptions()
|
81
|
+
else if rule_type.search(/Monthly/) != -1
|
82
|
+
@freq_select.prop('selectedIndex', 2)
|
83
|
+
@initMonthlyOptions()
|
84
|
+
else if rule_type.search(/Yearly/) != -1
|
85
|
+
@freq_select.prop('selectedIndex', 3)
|
86
|
+
@initYearlyOptions()
|
87
|
+
else
|
88
|
+
@initDailyOptions()
|
89
|
+
@freq_select.on "change", @freqChanged
|
90
|
+
|
91
|
+
initDailyOptions: ->
|
92
|
+
section = @content.find('.daily_options')
|
93
|
+
interval_input = section.find('.rs_daily_interval')
|
94
|
+
interval_input.val(@current_rule.hash.interval)
|
95
|
+
interval_input.off "change keyup"
|
96
|
+
interval_input.on "change keyup", @intervalChanged
|
97
|
+
section.show()
|
98
|
+
|
99
|
+
initWeeklyOptions: ->
|
100
|
+
section = @content.find('.weekly_options')
|
101
|
+
|
102
|
+
# connect the interval field
|
103
|
+
interval_input = section.find('.rs_weekly_interval')
|
104
|
+
interval_input.val(@current_rule.hash.interval)
|
105
|
+
interval_input.off "change keyup"
|
106
|
+
interval_input.on "change keyup", @intervalChanged
|
107
|
+
|
108
|
+
# connect the day fields
|
109
|
+
if @current_rule.hash.validations? && @current_rule.hash.validations.day?
|
110
|
+
$(@current_rule.hash.validations.day).each (index, val) ->
|
111
|
+
section.find(".day_holder a[data-value='"+val+"']").addClass("selected")
|
112
|
+
section.off "click"
|
113
|
+
section.on "click", ".day_holder a", @daysChanged
|
114
|
+
|
115
|
+
section.show()
|
116
|
+
|
117
|
+
initMonthlyOptions: ->
|
118
|
+
section = @content.find('.monthly_options')
|
119
|
+
interval_input = section.find('.rs_monthly_interval')
|
120
|
+
interval_input.val(@current_rule.hash.interval)
|
121
|
+
interval_input.off "change keyup"
|
122
|
+
interval_input.on "change keyup", @intervalChanged
|
123
|
+
|
124
|
+
@current_rule.hash.validations ||= {}
|
125
|
+
@current_rule.hash.validations.day_of_month ||= []
|
126
|
+
@current_rule.hash.validations.day_of_week ||= {}
|
127
|
+
@init_calendar_days(section)
|
128
|
+
@init_calendar_weeks(section)
|
129
|
+
|
130
|
+
in_week_mode = Object.keys(@current_rule.hash.validations.day_of_week).length > 0
|
131
|
+
section.find(".monthly_rule_type_week").prop("checked", in_week_mode)
|
132
|
+
section.find(".monthly_rule_type_day").prop("checked", !in_week_mode)
|
133
|
+
@toggle_month_view()
|
134
|
+
section.off "change"
|
135
|
+
section.find("input[name=monthly_rule_type]").on "change", @toggle_month_view
|
136
|
+
section.show()
|
137
|
+
|
138
|
+
initYearlyOptions: ->
|
139
|
+
section = @content.find('.yearly_options')
|
140
|
+
interval_input = section.find('.rs_yearly_interval')
|
141
|
+
interval_input.val(@current_rule.hash.interval)
|
142
|
+
interval_input.off "change keyup"
|
143
|
+
interval_input.on "change keyup", @intervalChanged
|
144
|
+
section.show()
|
145
|
+
|
146
|
+
|
147
|
+
summaryInit: ->
|
148
|
+
@summary = @outer_holder.find(".rs_summary")
|
149
|
+
@summaryUpdate()
|
150
|
+
|
151
|
+
# ========================= render methods ===============================
|
152
|
+
|
153
|
+
summaryUpdate: (new_string) =>
|
154
|
+
@summary.width @content.width()
|
155
|
+
if @current_rule.hash? && @current_rule.str?
|
156
|
+
@summary.removeClass "fetching"
|
157
|
+
@save_button.removeClass("disabled")
|
158
|
+
rule_str = @current_rule.str.replace("*", "")
|
159
|
+
if rule_str.length < 20
|
160
|
+
rule_str = "#{$.fn.recurring_select.texts["summary"]}: "+rule_str
|
161
|
+
@summary.find("span").html rule_str
|
162
|
+
else
|
163
|
+
@summary.addClass "fetching"
|
164
|
+
@save_button.addClass("disabled")
|
165
|
+
@summary.find("span").html ""
|
166
|
+
@summaryFetch()
|
167
|
+
|
168
|
+
summaryFetch: ->
|
169
|
+
return if !(@current_rule.hash? && (rule_type = @current_rule.hash.rule_type)?)
|
170
|
+
@content.css {"width": @content.width()+"px"}
|
171
|
+
$.ajax
|
172
|
+
url: "/recurring_select/translate",
|
173
|
+
type: "POST",
|
174
|
+
data: @current_rule.hash
|
175
|
+
success: @summaryFetchSuccess
|
176
|
+
|
177
|
+
summaryFetchSuccess: (data) =>
|
178
|
+
@current_rule.str = data
|
179
|
+
@summaryUpdate()
|
180
|
+
@content.css {"width": "auto"}
|
181
|
+
|
182
|
+
init_calendar_days: (section) =>
|
183
|
+
monthly_calendar = section.find(".rs_calendar_day")
|
184
|
+
monthly_calendar.html ""
|
185
|
+
for num in [1..31]
|
186
|
+
monthly_calendar.append (day_link = $(document.createElement("a")).text(num))
|
187
|
+
if $.inArray(num, @current_rule.hash.validations.day_of_month) != -1
|
188
|
+
day_link.addClass("selected")
|
189
|
+
|
190
|
+
# add last day of month button
|
191
|
+
monthly_calendar.append (end_of_month_link = $(document.createElement("a")).text($.fn.recurring_select.texts["last_day"]))
|
192
|
+
end_of_month_link.addClass("end_of_month")
|
193
|
+
if $.inArray(-1, @current_rule.hash.validations.day_of_month) != -1
|
194
|
+
end_of_month_link.addClass("selected")
|
195
|
+
|
196
|
+
monthly_calendar.find("a").on "click tap", @dateOfMonthChanged
|
197
|
+
|
198
|
+
init_calendar_weeks: (section) =>
|
199
|
+
monthly_calendar = section.find(".rs_calendar_week")
|
200
|
+
monthly_calendar.html ""
|
201
|
+
row_labels = $.fn.recurring_select.texts["order"]
|
202
|
+
cell_str = $.fn.recurring_select.texts["days_first_letter"]
|
203
|
+
|
204
|
+
for num in [1..4]
|
205
|
+
monthly_calendar.append "<span>#{row_labels[num - 1]}</span>"
|
206
|
+
for day_of_week in [0..6]
|
207
|
+
day_link = $("<a>", {text: cell_str[day_of_week]})
|
208
|
+
day_link.attr("day", day_of_week)
|
209
|
+
day_link.attr("instance", num)
|
210
|
+
monthly_calendar.append day_link
|
211
|
+
$.each @current_rule.hash.validations.day_of_week, (key, value) ->
|
212
|
+
$.each value, (index, instance) ->
|
213
|
+
section.find("a[day='#{key}'][instance='#{instance}']").addClass("selected")
|
214
|
+
monthly_calendar.find("a").on "click tap", @weekOfMonthChanged
|
215
|
+
|
216
|
+
toggle_month_view: =>
|
217
|
+
week_mode = @content.find(".monthly_rule_type_week").prop("checked")
|
218
|
+
@content.find(".rs_calendar_week").toggle(week_mode)
|
219
|
+
@content.find(".rs_calendar_day").toggle(!week_mode)
|
220
|
+
|
221
|
+
# ========================= Change callbacks ===============================
|
222
|
+
|
223
|
+
freqChanged: =>
|
224
|
+
@current_rule.hash = null unless $.isPlainObject(@current_rule.hash) # for custom values
|
225
|
+
|
226
|
+
@current_rule.hash ||= {}
|
227
|
+
@current_rule.hash.interval = 1
|
228
|
+
@current_rule.hash.until = null
|
229
|
+
@current_rule.hash.count = null
|
230
|
+
@current_rule.hash.validations = null
|
231
|
+
@content.find(".freq_option_section").hide();
|
232
|
+
@content.find("input[type=radio], input[type=checkbox]").prop("checked", false)
|
233
|
+
switch @freq_select.val()
|
234
|
+
when "Weekly"
|
235
|
+
@current_rule.hash.rule_type = "IceCube::WeeklyRule"
|
236
|
+
@current_rule.str = $.fn.recurring_select.texts["weekly"]
|
237
|
+
@initWeeklyOptions()
|
238
|
+
when "Monthly"
|
239
|
+
@current_rule.hash.rule_type = "IceCube::MonthlyRule"
|
240
|
+
@current_rule.str = $.fn.recurring_select.texts["monthly"]
|
241
|
+
@initMonthlyOptions()
|
242
|
+
when "Yearly"
|
243
|
+
@current_rule.hash.rule_type = "IceCube::YearlyRule"
|
244
|
+
@current_rule.str = $.fn.recurring_select.texts["yearly"]
|
245
|
+
@initYearlyOptions()
|
246
|
+
else
|
247
|
+
@current_rule.hash.rule_type = "IceCube::DailyRule"
|
248
|
+
@current_rule.str = $.fn.recurring_select.texts["daily"]
|
249
|
+
@initDailyOptions()
|
250
|
+
@summaryUpdate()
|
251
|
+
@positionDialogVert()
|
252
|
+
|
253
|
+
intervalChanged: (event) =>
|
254
|
+
@current_rule.str = null
|
255
|
+
@current_rule.hash ||= {}
|
256
|
+
@current_rule.hash.interval = parseInt($(event.currentTarget).val())
|
257
|
+
if @current_rule.hash.interval < 1 || isNaN(@current_rule.hash.interval)
|
258
|
+
@current_rule.hash.interval = 1
|
259
|
+
# $(event.currentTarget).val(@current_rule.hash.interval)
|
260
|
+
@summaryUpdate()
|
261
|
+
|
262
|
+
daysChanged: (event) =>
|
263
|
+
$(event.currentTarget).toggleClass("selected")
|
264
|
+
@current_rule.str = null
|
265
|
+
@current_rule.hash ||= {}
|
266
|
+
@current_rule.hash.validations = {}
|
267
|
+
raw_days = @content.find(".day_holder a.selected").map -> parseInt($(this).data("value"))
|
268
|
+
@current_rule.hash.validations.day = raw_days.get()
|
269
|
+
@summaryUpdate()
|
270
|
+
false # this prevents default and propogation
|
271
|
+
|
272
|
+
dateOfMonthChanged: (event) =>
|
273
|
+
$(event.currentTarget).toggleClass("selected")
|
274
|
+
@current_rule.str = null
|
275
|
+
@current_rule.hash ||= {}
|
276
|
+
@current_rule.hash.validations = {}
|
277
|
+
raw_days = @content.find(".monthly_options .rs_calendar_day a.selected").map ->
|
278
|
+
res = if $(this).text() == $.fn.recurring_select.texts["last_day"] then -1 else parseInt($(this).text())
|
279
|
+
res
|
280
|
+
@current_rule.hash.validations.day_of_week = {}
|
281
|
+
@current_rule.hash.validations.day_of_month = raw_days.get()
|
282
|
+
@summaryUpdate()
|
283
|
+
false
|
284
|
+
|
285
|
+
weekOfMonthChanged: (event) =>
|
286
|
+
$(event.currentTarget).toggleClass("selected")
|
287
|
+
@current_rule.str = null
|
288
|
+
@current_rule.hash ||= {}
|
289
|
+
@current_rule.hash.validations = {}
|
290
|
+
@current_rule.hash.validations.day_of_month = []
|
291
|
+
@current_rule.hash.validations.day_of_week = {}
|
292
|
+
@content.find(".monthly_options .rs_calendar_week a.selected").each (index, elm) =>
|
293
|
+
day = parseInt($(elm).attr("day"))
|
294
|
+
instance = parseInt($(elm).attr("instance"))
|
295
|
+
@current_rule.hash.validations.day_of_week[day] ||= []
|
296
|
+
@current_rule.hash.validations.day_of_week[day].push instance
|
297
|
+
@summaryUpdate()
|
298
|
+
false
|
299
|
+
|
300
|
+
# ========================= Change callbacks ===============================
|
301
|
+
|
302
|
+
template: () ->
|
303
|
+
str = "
|
304
|
+
<div class='rs_dialog_holder'>
|
305
|
+
<div class='rs_dialog'>
|
306
|
+
<div class='rs_dialog_content'>
|
307
|
+
<h1>#{$.fn.recurring_select.texts["repeat"]} <a href='#' title='#{$.fn.recurring_select.texts["cancel"]}' Alt='#{$.fn.recurring_select.texts["cancel"]}'></a> </h1>
|
308
|
+
<p>
|
309
|
+
<label for='rs_frequency'>#{$.fn.recurring_select.texts["frequency"]}:</label>
|
310
|
+
<select id='rs_frequency' class='rs_frequency' name='rs_frequency'>
|
311
|
+
<option value='Daily'>#{$.fn.recurring_select.texts["daily"]}</option>
|
312
|
+
<option value='Weekly'>#{$.fn.recurring_select.texts["weekly"]}</option>
|
313
|
+
<option value='Monthly'>#{$.fn.recurring_select.texts["monthly"]}</option>
|
314
|
+
<option value='Yearly'>#{$.fn.recurring_select.texts["yearly"]}</option>
|
315
|
+
</select>
|
316
|
+
</p>
|
317
|
+
|
318
|
+
<div class='daily_options freq_option_section'>
|
319
|
+
<p>
|
320
|
+
#{$.fn.recurring_select.texts["every"]}
|
321
|
+
<input type='text' name='rs_daily_interval' class='rs_daily_interval rs_interval' value='1' size='2' />
|
322
|
+
#{$.fn.recurring_select.texts["days"]}
|
323
|
+
</p>
|
324
|
+
</div>
|
325
|
+
<div class='weekly_options freq_option_section'>
|
326
|
+
<p>
|
327
|
+
#{$.fn.recurring_select.texts["every"]}
|
328
|
+
<input type='text' name='rs_weekly_interval' class='rs_weekly_interval rs_interval' value='1' size='2' />
|
329
|
+
#{$.fn.recurring_select.texts["weeks_on"]}:
|
330
|
+
</p>
|
331
|
+
<div class='day_holder'>
|
332
|
+
"
|
333
|
+
for day_of_week in [$.fn.recurring_select.texts["first_day_of_week"]...(7 + $.fn.recurring_select.texts["first_day_of_week"])]
|
334
|
+
day_of_week = day_of_week % 7
|
335
|
+
str += "<a href='#' data-value='#{day_of_week}'>#{$.fn.recurring_select.texts["days_first_letter"][day_of_week]}</a>"
|
336
|
+
|
337
|
+
str += "
|
338
|
+
</div>
|
339
|
+
<span style='clear:both; visibility:hidden; height:1px;'>.</span>
|
340
|
+
</div>
|
341
|
+
<div class='monthly_options freq_option_section'>
|
342
|
+
<p>
|
343
|
+
#{$.fn.recurring_select.texts["every"]}
|
344
|
+
<input type='text' name='rs_monthly_interval' class='rs_monthly_interval rs_interval' value='1' size='2' />
|
345
|
+
#{$.fn.recurring_select.texts["months"]}:
|
346
|
+
</p>
|
347
|
+
<p class='monthly_rule_type'>
|
348
|
+
<span>#{$.fn.recurring_select.texts["day_of_month"]} <input type='radio' class='monthly_rule_type_day' name='monthly_rule_type' value='true' /></span>
|
349
|
+
<span>#{$.fn.recurring_select.texts["day_of_week"]} <input type='radio' class='monthly_rule_type_week' name='monthly_rule_type' value='true' /></span>
|
350
|
+
</p>
|
351
|
+
<p class='rs_calendar_day'></p>
|
352
|
+
<p class='rs_calendar_week'></p>
|
353
|
+
</div>
|
354
|
+
<div class='yearly_options freq_option_section'>
|
355
|
+
<p>
|
356
|
+
#{$.fn.recurring_select.texts["every"]}
|
357
|
+
<input type='text' name='rs_yearly_interval' class='rs_yearly_interval rs_interval' value='1' size='2' />
|
358
|
+
#{$.fn.recurring_select.texts["years"]}
|
359
|
+
</p>
|
360
|
+
</div>
|
361
|
+
<p class='rs_summary'>
|
362
|
+
<span></span>
|
363
|
+
</p>
|
364
|
+
<div class='controls'>
|
365
|
+
<input type='button' class='rs_save' value='#{$.fn.recurring_select.texts["ok"]}' />
|
366
|
+
<input type='button' class='rs_cancel' value='#{$.fn.recurring_select.texts["cancel"]}' />
|
367
|
+
</div>
|
368
|
+
</div>
|
369
|
+
</div>
|
370
|
+
</div>
|
371
|
+
"
|