recurring_select 3.0.0 → 4.0.0.rc1

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.
@@ -0,0 +1,447 @@
1
+ //= require utils
2
+ //= require defaults
3
+
4
+ class RecurringSelectDialog {
5
+ constructor(recurring_selector) {
6
+ this.config = this.constructor.config
7
+ this.cancel = this.cancel.bind(this);
8
+ this.outerCancel = this.outerCancel.bind(this);
9
+ this.save = this.save.bind(this);
10
+ this.summaryUpdate = this.summaryUpdate.bind(this);
11
+ this.summaryFetchSuccess = this.summaryFetchSuccess.bind(this);
12
+ this.init_calendar_days = this.init_calendar_days.bind(this);
13
+ this.init_calendar_weeks = this.init_calendar_weeks.bind(this);
14
+ this.toggle_month_view = this.toggle_month_view.bind(this);
15
+ this.freqChanged = this.freqChanged.bind(this);
16
+ this.intervalChanged = this.intervalChanged.bind(this);
17
+ this.daysChanged = this.daysChanged.bind(this);
18
+ this.dateOfMonthChanged = this.dateOfMonthChanged.bind(this);
19
+ this.weekOfMonthChanged = this.weekOfMonthChanged.bind(this);
20
+ this.recurring_selector = recurring_selector;
21
+ this.current_rule = this.recurring_selector.recurring_select('current_rule');
22
+ this.initDialogBox();
23
+ if ((this.current_rule.hash == null) || (this.current_rule.hash.rule_type == null)) {
24
+ this.freqChanged();
25
+ }
26
+ }
27
+
28
+ initDialogBox() {
29
+ document.querySelectorAll(".rs_dialog_holder").forEach(el => el.parentNode.removeChild(el))
30
+
31
+ const uiPage = document.querySelector('.ui-page-active')
32
+ const anchor = uiPage ? uiPage : document.body
33
+
34
+ const div = document.createElement("div")
35
+ div.innerHTML = this.template()
36
+ anchor.appendChild(div.children[0])
37
+
38
+ this.outer_holder = document.querySelector(".rs_dialog_holder");
39
+ this.inner_holder = this.outer_holder.querySelector(".rs_dialog");
40
+ this.content = this.outer_holder.querySelector(".rs_dialog_content");
41
+
42
+ this.mainEventInit();
43
+ this.freqInit();
44
+ this.summaryInit();
45
+ trigger(this.outer_holder, "recurring_select:dialog_opened");
46
+ this.freq_select.focus();
47
+ }
48
+
49
+ cancel() {
50
+ this.outer_holder.remove();
51
+ this.recurring_selector.recurring_select('cancel');
52
+ }
53
+
54
+ outerCancel(event) {
55
+ if (event.target.classList.contains("rs_dialog_holder")) {
56
+ this.cancel();
57
+ }
58
+ }
59
+
60
+ save() {
61
+ if ((this.current_rule.str == null)) { return; }
62
+ this.outer_holder.remove();
63
+ this.recurring_selector.recurring_select('save', this.current_rule);
64
+ }
65
+
66
+ // ========================= Init Methods ===============================
67
+
68
+ mainEventInit() {
69
+ // Tap hooks are for jQueryMobile
70
+ on(this.outer_holder, 'click tap', this.outerCancel);
71
+ on(this.content, 'click tap', 'h1 a', this.cancel);
72
+ this.save_button = this.content.querySelector('input.rs_save')
73
+ on(this.save_button, "click tap", this.save)
74
+ on(this.content.querySelector('input.rs_cancel'), "click tap", this.cancel)
75
+ }
76
+
77
+ freqInit() {
78
+ this.freq_select = this.outer_holder.querySelector(".rs_frequency");
79
+ const rule_type = this.current_rule.hash && this.current_rule.hash.rule_type
80
+ if (this.current_rule.hash != null && rule_type != null) {
81
+ if (rule_type.search(/Weekly/) !== -1) {
82
+ this.freq_select.selectedIndex = 1
83
+ this.initWeeklyOptions();
84
+ } else if (rule_type.search(/Monthly/) !== -1) {
85
+ this.freq_select.selectedIndex = 2
86
+ this.initMonthlyOptions();
87
+ } else if (rule_type.search(/Yearly/) !== -1) {
88
+ this.freq_select.selectedIndex = 3
89
+ this.initYearlyOptions();
90
+ } else {
91
+ this.initDailyOptions();
92
+ }
93
+ }
94
+ on(this.freq_select, "change", this.freqChanged);
95
+ }
96
+
97
+ initDailyOptions() {
98
+ const section = this.content.querySelector('.daily_options')
99
+ const interval_input = section.querySelector('.rs_daily_interval')
100
+ interval_input.value = this.current_rule.hash.interval
101
+ on(interval_input, "change keyup", this.intervalChanged);
102
+ section.style.display = 'block'
103
+ }
104
+
105
+ initWeeklyOptions() {
106
+ const section = this.content.querySelector('.weekly_options');
107
+
108
+ // connect the interval field
109
+ const interval_input = section.querySelector('.rs_weekly_interval');
110
+ interval_input.value = this.current_rule.hash.interval
111
+ on(interval_input, "change keyup", this.intervalChanged);
112
+
113
+ // clear selected days
114
+ section.querySelectorAll(".day_holder a").forEach(el =>
115
+ el.classList.remove("selected")
116
+ )
117
+
118
+ // connect the day fields
119
+ if ((this.current_rule.hash.validations != null) && (this.current_rule.hash.validations.day != null)) {
120
+ Array.from(this.current_rule.hash.validations.day).forEach((val) =>
121
+ section.querySelector(".day_holder a[data-value='"+val+"']").classList.add("selected")
122
+ )
123
+ }
124
+
125
+ off(section, "click")
126
+ on(section, "click", ".day_holder a", this.daysChanged)
127
+
128
+ section.style.display = 'block'
129
+ }
130
+
131
+ initMonthlyOptions() {
132
+ const section = this.content.querySelector('.monthly_options')
133
+ const interval_input = section.querySelector('.rs_monthly_interval')
134
+ interval_input.value = this.current_rule.hash.interval
135
+ on(interval_input, "change keyup", this.intervalChanged)
136
+
137
+ if (!this.current_rule.hash.validations) { this.current_rule.hash.validations = {} };
138
+ if (!this.current_rule.hash.validations.day_of_month) { this.current_rule.hash.validations.day_of_month = [] };
139
+ if (!this.current_rule.hash.validations.day_of_week) { this.current_rule.hash.validations.day_of_week = {} };
140
+ this.init_calendar_days(section);
141
+ this.init_calendar_weeks(section);
142
+
143
+ const in_week_mode = Object.keys(this.current_rule.hash.validations.day_of_week).length > 0;
144
+ section.querySelector(".monthly_rule_type_week").checked = in_week_mode
145
+ section.querySelector(".monthly_rule_type_day").checked = !in_week_mode;
146
+ this.toggle_month_view();
147
+ section.querySelectorAll("input[name=monthly_rule_type]").forEach((el) => on(el, "change", this.toggle_month_view))
148
+ section.style.display = 'block'
149
+ }
150
+
151
+ initYearlyOptions() {
152
+ const section = this.content.querySelector('.yearly_options');
153
+ const interval_input = section.querySelector('.rs_yearly_interval');
154
+ interval_input.value = this.current_rule.hash.interval
155
+ on(interval_input, "change keyup", this.intervalChanged)
156
+ section.style.display = 'block'
157
+ }
158
+
159
+
160
+ summaryInit() {
161
+ this.summary = this.outer_holder.querySelector(".rs_summary");
162
+ this.summaryUpdate();
163
+ }
164
+
165
+ // ========================= render methods ===============================
166
+
167
+ summaryUpdate(new_string) {
168
+ // this.summary.style.width = `${this.content.getBoundingClientRect().width}px`;
169
+ if ((this.current_rule.hash != null) && (this.current_rule.str != null)) {
170
+ this.summary.classList.remove("fetching");
171
+ this.save_button.classList.remove("disabled");
172
+ let rule_str = this.current_rule.str.replace("*", "");
173
+ if (rule_str.length < 20) {
174
+ rule_str = `${this.config.texts["summary"]}: `+rule_str;
175
+ }
176
+ this.summary.querySelector("span").textContent = rule_str
177
+ } else {
178
+ this.summary.classList.add("fetching");
179
+ this.save_button.classList.add("disabled");
180
+ this.summary.querySelector("span").textContent = ""
181
+ this.summaryFetch();
182
+ }
183
+ }
184
+
185
+ summaryFetch() {
186
+ if (!(this.current_rule.hash != null && this.current_rule.hash.rule_type != null)) { return; }
187
+ this.current_rule.hash['week_start'] = this.config.texts["first_day_of_week"];
188
+
189
+ const url = `<%= Rails.application.config.action_controller.relative_url_root %>/recurring_select/translate/${this.config.texts["locale_iso_code"]}`
190
+ const headers = { 'X-Requested-With' : 'XMLHttpRequest', 'Content-Type' : 'application/x-www-form-urlencoded' }
191
+ const body = serialize(this.current_rule.hash)
192
+ console.log(this.current_rule.hash, body)
193
+
194
+ fetch(url, { method: "POST", body, headers })
195
+ .then(r => r.text())
196
+ .then(this.summaryFetchSuccess)
197
+ }
198
+
199
+ summaryFetchSuccess(data) {
200
+ this.current_rule.str = data
201
+ this.summaryUpdate()
202
+ css(this.content, { width: "auto" })
203
+ }
204
+
205
+ init_calendar_days(section) {
206
+ const monthly_calendar = section.querySelector(".rs_calendar_day");
207
+ monthly_calendar.innerHTML = "";
208
+ for (let num = 1; num <= 31; num++) {
209
+ const day_link = document.createElement("a")
210
+ day_link.innerText = num
211
+ monthly_calendar.appendChild(day_link)
212
+ if (Array.from(this.current_rule.hash.validations.day_of_month).includes(num)) {
213
+ day_link.classList.add("selected");
214
+ }
215
+ };
216
+
217
+ // add last day of month button
218
+ const end_of_month_link = document.createElement("a")
219
+ end_of_month_link.innerText = this.config.texts["last_day"]
220
+ monthly_calendar.appendChild(end_of_month_link);
221
+ end_of_month_link.classList.add("end_of_month");
222
+ if (Array.from(this.current_rule.hash.validations.day_of_month).includes(-1)) {
223
+ end_of_month_link.classList.add("selected");
224
+ }
225
+
226
+ off(monthly_calendar, "click tap")
227
+ on(monthly_calendar, "click tap", "a", this.dateOfMonthChanged)
228
+ }
229
+
230
+ init_calendar_weeks(section) {
231
+ const monthly_calendar = section.querySelector(".rs_calendar_week")
232
+ monthly_calendar.innerHTML = ""
233
+ const row_labels = this.config.texts["order"];
234
+ const show_row = this.config.options["monthly"]["show_week"];
235
+ const cell_str = this.config.texts["days_first_letter"];
236
+
237
+ const iterable = [1, 2, 3, 4, 5, -1]
238
+ for (let index = 0; index < iterable.length; index++) {
239
+ const num = iterable[index];
240
+ if (show_row[index]) {
241
+ const el = document.createElement("span")
242
+ el.innerText = row_labels[index]
243
+ monthly_calendar.appendChild(el);
244
+ for (let i = this.config.texts["first_day_of_week"], day_of_week = i, end = 7 + this.config.texts["first_day_of_week"], asc = this.config.texts["first_day_of_week"] <= end; asc ? i < end : i > end; asc ? i++ : i--, day_of_week = i) {
245
+ day_of_week = day_of_week % 7;
246
+ const day_link = document.createElement("a")
247
+ day_link.innerText = cell_str[day_of_week]
248
+ day_link.setAttribute("day", day_of_week);
249
+ day_link.setAttribute("instance", num);
250
+ monthly_calendar.appendChild(day_link);
251
+ };
252
+ }
253
+ };
254
+
255
+ Object.entries(this.current_rule.hash.validations.day_of_week).forEach(([key, value]) => {
256
+ Array.from(value).forEach((instance, index) => {
257
+ section.querySelector(`a[day='${key}'][instance='${instance}']`).classList.add("selected")
258
+ })
259
+ })
260
+
261
+ off(monthly_calendar, "click tap")
262
+ on(monthly_calendar, "click tap", "a", this.weekOfMonthChanged)
263
+ }
264
+
265
+ toggle_month_view() {
266
+ const week_mode = this.content.querySelector(".monthly_rule_type_week").checked
267
+ if (week_mode) {
268
+ this.content.querySelector(".rs_calendar_week").style.display = "block"
269
+ this.content.querySelector(".rs_calendar_day").style.display = "none"
270
+ } else {
271
+ this.content.querySelector(".rs_calendar_week").style.display = "none"
272
+ this.content.querySelector(".rs_calendar_day").style.display = "block"
273
+ }
274
+ }
275
+
276
+ // ========================= Change callbacks ===============================
277
+
278
+ freqChanged() {
279
+ if (!isPlainObject(this.current_rule.hash)) { this.current_rule.hash = null; } // for custom values
280
+
281
+ if (!this.current_rule.hash) { this.current_rule.hash = {} };
282
+ this.current_rule.hash.interval = 1;
283
+ this.current_rule.hash.until = null;
284
+ this.current_rule.hash.count = null;
285
+ this.current_rule.hash.validations = null;
286
+ this.content.querySelectorAll(".freq_option_section").forEach(el => el.style.display = 'none')
287
+ this.content.querySelector("input[type=radio], input[type=checkbox]").checked = false
288
+ switch (this.freq_select.value) {
289
+ case "Weekly":
290
+ this.current_rule.hash.rule_type = "IceCube::WeeklyRule";
291
+ this.current_rule.str = this.config.texts["weekly"];
292
+ this.initWeeklyOptions();
293
+ break
294
+ case "Monthly":
295
+ this.current_rule.hash.rule_type = "IceCube::MonthlyRule";
296
+ this.current_rule.str = this.config.texts["monthly"];
297
+ this.initMonthlyOptions();
298
+ break
299
+ case "Yearly":
300
+ this.current_rule.hash.rule_type = "IceCube::YearlyRule";
301
+ this.current_rule.str = this.config.texts["yearly"];
302
+ this.initYearlyOptions();
303
+ break
304
+ default:
305
+ this.current_rule.hash.rule_type = "IceCube::DailyRule";
306
+ this.current_rule.str = this.config.texts["daily"];
307
+ this.initDailyOptions();
308
+ };
309
+ this.summaryUpdate();
310
+ }
311
+
312
+ intervalChanged(event) {
313
+ this.current_rule.str = null;
314
+ if (!this.current_rule.hash) { this.current_rule.hash = {} };
315
+ this.current_rule.hash.interval = parseInt(event.currentTarget.value);
316
+ if ((this.current_rule.hash.interval < 1) || isNaN(this.current_rule.hash.interval)) {
317
+ this.current_rule.hash.interval = 1;
318
+ }
319
+ this.summaryUpdate();
320
+ }
321
+
322
+ daysChanged(event) {
323
+ event.target.classList.toggle("selected");
324
+ this.current_rule.str = null;
325
+ if (!this.current_rule.hash) { this.current_rule.hash = {} };
326
+ this.current_rule.hash.validations = {};
327
+ const raw_days = Array.from(this.content.querySelectorAll(".day_holder a.selected"))
328
+ .map(el => parseInt(el.dataset.value))
329
+ this.current_rule.hash.validations.day = raw_days
330
+ this.summaryUpdate();
331
+ return false;
332
+ }
333
+
334
+ dateOfMonthChanged(event) {
335
+ event.target.classList.toggle("selected");
336
+ this.current_rule.str = null;
337
+ if (!this.current_rule.hash) { this.current_rule.hash = {} };
338
+ this.current_rule.hash.validations = {};
339
+ const raw_days = Array.from(this.content.querySelectorAll(".monthly_options .rs_calendar_day a.selected"))
340
+ .map(el => {
341
+ return el.innerText === this.config.texts["last_day"] ? -1 : parseInt(el.innerText)
342
+ })
343
+ this.current_rule.hash.validations.day_of_week = {};
344
+ this.current_rule.hash.validations.day_of_month = raw_days;
345
+ this.summaryUpdate();
346
+ return false;
347
+ }
348
+
349
+ weekOfMonthChanged(event) {
350
+ event.target.classList.toggle("selected");
351
+ this.current_rule.str = null;
352
+ if (!this.current_rule.hash) { this.current_rule.hash = {} };
353
+ this.current_rule.hash.validations = {};
354
+ this.current_rule.hash.validations.day_of_month = [];
355
+ this.current_rule.hash.validations.day_of_week = {};
356
+ this.content.querySelectorAll(".monthly_options .rs_calendar_week a.selected")
357
+ .forEach((elm, index) => {
358
+ const day = parseInt(elm.getAttribute("day"));
359
+ const instance = parseInt(elm.getAttribute("instance"));
360
+ if (!this.current_rule.hash.validations.day_of_week[day]) { this.current_rule.hash.validations.day_of_week[day] = [] };
361
+ return this.current_rule.hash.validations.day_of_week[day].push(instance);
362
+ })
363
+ this.summaryUpdate();
364
+ return false;
365
+ }
366
+
367
+ // ========================= Change callbacks ===============================
368
+
369
+ template() {
370
+ let str = `\
371
+ <div class='rs_dialog_holder'> \
372
+ <div class='rs_dialog'> \
373
+ <div class='rs_dialog_content'> \
374
+ <h1>${this.config.texts["repeat"]} <a href='javascript:void(0)' title='${this.config.texts["cancel"]}' alt='${this.config.texts["cancel"]}'></a> </h1> \
375
+ <p class='frequency-select-wrapper'> \
376
+ <label for='rs_frequency'>${this.config.texts["frequency"]}:</label> \
377
+ <select data-wrapper-class='ui-recurring-select' id='rs_frequency' class='rs_frequency' name='rs_frequency'> \
378
+ <option value='Daily'>${this.config.texts["daily"]}</option> \
379
+ <option value='Weekly'>${this.config.texts["weekly"]}</option> \
380
+ <option value='Monthly'>${this.config.texts["monthly"]}</option> \
381
+ <option value='Yearly'>${this.config.texts["yearly"]}</option> \
382
+ </select> \
383
+ </p> \
384
+ \
385
+ <div class='daily_options freq_option_section'> \
386
+ <p> \
387
+ ${this.config.texts["every"]} \
388
+ <input type='text' data-wrapper-class='ui-recurring-select' name='rs_daily_interval' class='rs_daily_interval rs_interval' value='1' size='2' /> \
389
+ ${this.config.texts["days"]} \
390
+ </p> \
391
+ </div> \
392
+ <div class='weekly_options freq_option_section'> \
393
+ <p> \
394
+ ${this.config.texts["every"]} \
395
+ <input type='text' data-wrapper-class='ui-recurring-select' name='rs_weekly_interval' class='rs_weekly_interval rs_interval' value='1' size='2' /> \
396
+ ${this.config.texts["weeks_on"]}: \
397
+ </p> \
398
+ <div class='day_holder'>\
399
+ `;
400
+ for (let i = this.config.texts["first_day_of_week"], day_of_week = i, end = 7 + this.config.texts["first_day_of_week"], asc = this.config.texts["first_day_of_week"] <= end; asc ? i < end : i > end; asc ? i++ : i--, day_of_week = i) {
401
+ day_of_week = day_of_week % 7;
402
+ str += `<a href='#' data-value='${day_of_week}'>${this.config.texts["days_first_letter"][day_of_week]}</a>`;
403
+ };
404
+
405
+ str += `\
406
+ </div> \
407
+ <span style='clear:both; visibility:hidden; height:1px;'>.</span> \
408
+ </div> \
409
+ <div class='monthly_options freq_option_section'> \
410
+ <p> \
411
+ ${this.config.texts["every"]} \
412
+ <input type='text' data-wrapper-class='ui-recurring-select' name='rs_monthly_interval' class='rs_monthly_interval rs_interval' value='1' size='2' /> \
413
+ ${this.config.texts["months"]}: \
414
+ </p> \
415
+ <p class='monthly_rule_type'> \
416
+ <span><label for='monthly_rule_type_day'>${this.config.texts["day_of_month"]}</label><input type='radio' class='monthly_rule_type_day' name='monthly_rule_type' id='monthly_rule_type_day' value='true' /></span> \
417
+ <span><label for='monthly_rule_type_week'>${this.config.texts["day_of_week"]}</label><input type='radio' class='monthly_rule_type_week' name='monthly_rule_type' id='monthly_rule_type_week' value='true' /></span> \
418
+ </p> \
419
+ <p class='rs_calendar_day'></p> \
420
+ <p class='rs_calendar_week'></p> \
421
+ </div> \
422
+ <div class='yearly_options freq_option_section'> \
423
+ <p> \
424
+ ${this.config.texts["every"]} \
425
+ <input type='text' data-wrapper-class='ui-recurring-select' name='rs_yearly_interval' class='rs_yearly_interval rs_interval' value='1' size='2' /> \
426
+ ${this.config.texts["years"]} \
427
+ </p> \
428
+ </div> \
429
+ <p class='rs_summary'> \
430
+ <span></span> \
431
+ </p> \
432
+ <div class='controls'> \
433
+ <input type='button' data-wrapper-class='ui-recurring-select' class='rs_save' value='${this.config.texts["ok"]}' /> \
434
+ <input type='button' data-wrapper-class='ui-recurring-select' class='rs_cancel' value='${this.config.texts["cancel"]}' /> \
435
+ </div> \
436
+ </div> \
437
+ </div> \
438
+ </div>\
439
+ `;
440
+
441
+ return str;
442
+ }
443
+ }
444
+
445
+ RecurringSelectDialog.config = defaultConfig
446
+
447
+ window.RecurringSelectDialog = RecurringSelectDialog
@@ -0,0 +1,70 @@
1
+ function css(el, styles) {
2
+ for (let rule in styles) {
3
+ el.style[rule] = styles[rule]
4
+ }
5
+ }
6
+
7
+ function trigger(el, eventName) {
8
+ el.dispatchEvent(new CustomEvent(eventName))
9
+ }
10
+
11
+ function isPlainObject(obj) {
12
+ return obj && obj.toString() === "[object Object]"
13
+ }
14
+
15
+ const eventHandlerRefsExpando = '__recurring_select_events'
16
+
17
+ function on(el, events, sel, handler) {
18
+ let eventHandler = sel
19
+ if (handler) {
20
+ eventHandler = (e) => {
21
+ if (e.target.matches(sel)) {
22
+ if (handler.call(this, e) === false) {
23
+ e.preventDefault()
24
+ e.stopPropagation()
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ el[eventHandlerRefsExpando] = el[eventHandlerRefsExpando] || []
31
+
32
+ events.trim().split(/ +/).forEach(type => {
33
+ el[eventHandlerRefsExpando].push([ type, eventHandler ])
34
+ el.addEventListener(type, eventHandler)
35
+ })
36
+ }
37
+
38
+ function off(el, events) {
39
+ const types = events.trim().split(/ +/)
40
+
41
+ el[eventHandlerRefsExpando] = (el[eventHandlerRefsExpando] || [])
42
+ .filter(([t, h], i) => {
43
+ if (types.includes(t)) {
44
+ el.removeEventListener(t, h)
45
+ return false
46
+ }
47
+ return true
48
+ })
49
+ }
50
+
51
+ function serialize(params, prefix) {
52
+ const query = Object.keys(params).map((key) => {
53
+ const value = params[key];
54
+
55
+ if (params.constructor === Array)
56
+ key = `${prefix}[]`;
57
+ else if (params.constructor === Object)
58
+ key = (prefix ? `${prefix}[${key}]` : key);
59
+
60
+ if (value === null)
61
+ return `${key}=`
62
+
63
+ if (typeof value === 'object')
64
+ return serialize(value, key);
65
+ else
66
+ return `${key}=${encodeURIComponent(value)}`;
67
+ });
68
+
69
+ return [].concat.apply([], query).join('&');
70
+ }
@@ -2,7 +2,9 @@
2
2
 
3
3
  /* -------- resets ---------------*/
4
4
 
5
- .rs_dialog_holder { font-size:14px; color:black;
5
+ .rs_dialog_holder {
6
+ font-size:14px;
7
+ color:black;
6
8
  a {color:black;}
7
9
  input[type=button] {
8
10
  font: small/normal Arial,sans-serif;
@@ -28,10 +30,29 @@ select {
28
30
  option.bold {font-weight:bold; color:red;}
29
31
  }
30
32
 
31
- .rs_dialog_holder { position:fixed; left:0px; right:0px; top:0px; bottom:0px; padding-left:50%; background-color:rgba(255,255,255,0.2); z-index:50;
32
- .rs_dialog { background-color:#f6f6f6; border:1px solid #acacac; @include shadows(1px, 3px, 8px, rgba(0,0,0,0.25)); @include rounded_corners(7px);
33
- display:inline-block; min-width:200px; margin-left:-125px; overflow:hidden; position:relative;
34
- .rs_dialog_content { padding:10px;
33
+ .rs_dialog_holder {
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ position: fixed;
38
+ left:0px;
39
+ right:0px;
40
+ top:0px;
41
+ bottom:0px;
42
+ background-color:rgba(255,255,255,0.2);
43
+ z-index:50;
44
+
45
+ .rs_dialog {
46
+ background-color:#f6f6f6;
47
+ border:1px solid #acacac;
48
+ @include shadows(1px, 3px, 8px, rgba(0,0,0,0.25));
49
+ @include rounded_corners(7px);
50
+ min-width:200px;
51
+ overflow:hidden;
52
+
53
+ .rs_dialog_content {
54
+ padding:10px;
55
+
35
56
  h1 { font-size:16px; padding:0px; margin:0 0 10px 0;
36
57
  a {float:right; display:inline-block; height:16px; width:16px; background-image:image-url("recurring_select/cancel.png"); background-position:center; background-repeat:no-repeat;}
37
58
  }
@@ -42,7 +63,8 @@ select {
42
63
 
43
64
  a { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
44
65
 
45
- .freq_option_section { display:none;
66
+ .freq_option_section {
67
+ display:none;
46
68
  label { font-weight: bold; }
47
69
  .rs_interval {width:30px; text-align:center; display: inline-block;}
48
70
 
@@ -77,7 +99,10 @@ select {
77
99
  }
78
100
 
79
101
 
80
- .rs_summary { padding:0px; margin-top:15px; border-top:1px solid #ccc;
102
+ .rs_summary {
103
+ padding: 0px;
104
+ margin-top: 15px;
105
+ border-top: 1px solid #ccc;
81
106
  span {font-weight:bold; border-top:1px solid #fff; display:block; padding:10px 0 5px 0;}
82
107
  &.fetching {color:#999;
83
108
  span {background-image:image-url("recurring_select/throbber_13x13.gif"); background-position:center; background-repeat:no-repeat; display:inline-block; height:13px; width:13px; margin-top:-4px; padding-right:5px;}
@@ -85,8 +110,11 @@ select {
85
110
  label {font-weight:normal;}
86
111
  }
87
112
 
88
- .controls { padding:10px 0px 5px 0px; min-width:170px; text-align:center;
89
- input[type=button] { margin:0px 5px; width:70px;
113
+ .controls {
114
+ padding:10px 0px 5px 0px;
115
+ min-width:170px;
116
+ text-align:center;
117
+ input[type=button] { margin:0px 5px;
90
118
  &.rs_save {color:#333; }
91
119
  &.rs_cancel {color:#666;}
92
120
  &.disabled {color:#aaa; }
@@ -6,6 +6,12 @@ module RecurringSelectHelper
6
6
  RecurringSelectTag.new(object, method, self, default_schedules, options, html_options).render
7
7
  end
8
8
  end
9
+
10
+ module FormTagHelper
11
+ def select_recurring_tag(name, default_schedules = nil, options = {}, html_options = {})
12
+ RecurringSelectTag.new(nil, name, self, default_schedules, options, html_options).render
13
+ end
14
+ end
9
15
 
10
16
  module FormBuilder
11
17
  def select_recurring(method, default_schedules = nil, options = {}, html_options = {})
@@ -65,7 +71,7 @@ module RecurringSelectHelper
65
71
  ar = [rule.to_s, rule.to_hash.to_json]
66
72
 
67
73
  if custom
68
- ar[0] << "*"
74
+ ar[0] += "*"
69
75
  ar << {"data-custom" => true}
70
76
  end
71
77
 
@@ -90,19 +96,15 @@ module RecurringSelectHelper
90
96
  end
91
97
  end
92
98
 
93
- class RecurringSelectTag < ActionView::Helpers::Tags::Base
99
+ class RecurringSelectTag < ActionView::Helpers::Tags::Select
94
100
  include RecurringSelectHelper::FormOptionsHelper
95
101
  include SelectHTMLOptions
96
102
 
97
103
  def initialize(object, method, template_object, default_schedules = nil, options = {}, html_options = {})
98
104
  @default_schedules = default_schedules
99
- @choices = @choices.to_a if @choices.is_a?(Range)
100
- @method_name = method.to_s
101
- @object_name = object.to_s
102
- @html_options = recurring_select_html_options(html_options)
103
- add_default_name_and_id(@html_options)
105
+ html_options = recurring_select_html_options(html_options)
104
106
 
105
- super(object, method, template_object, options)
107
+ super(object, method, template_object, @default_schedules, options, html_options)
106
108
  end
107
109
 
108
110
  def render
@@ -6,6 +6,7 @@ module RecurringSelect
6
6
 
7
7
  initializer "recurring_select.extending_form_builder" do |app|
8
8
  ActionView::Helpers::FormHelper.send(:include, RecurringSelectHelper::FormHelper)
9
+ ActionView::Helpers::FormTagHelper.send(:include, RecurringSelectHelper::FormTagHelper)
9
10
  ActionView::Helpers::FormOptionsHelper.send(:include, RecurringSelectHelper::FormOptionsHelper)
10
11
  ActionView::Helpers::FormBuilder.send(:include, RecurringSelectHelper::FormBuilder)
11
12
  end
@@ -1,3 +1,3 @@
1
1
  module RecurringSelect
2
- VERSION = "3.0.0"
2
+ VERSION = "4.0.0.rc1"
3
3
  end
@@ -59,7 +59,7 @@ module RecurringSelect
59
59
  # this is soooooo ugly
60
60
  if params[:validations][:day_of_week]
61
61
  params[:validations][:day_of_week] ||= {}
62
- if params[:validations][:day_of_week].length > 0 and not params[:validations][:day_of_week].keys.first =~ /\d/
62
+ if params[:validations][:day_of_week].length > 0 and not params[:validations][:day_of_week].keys.first.to_s =~ /\d/
63
63
  params[:validations][:day_of_week].symbolize_keys!
64
64
  else
65
65
  originals = params[:validations][:day_of_week].dup