tb_core 1.4.0.1 → 1.4.1
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 +4 -4
- data/app/assets/javascripts/admin/core/jquery_ui.js +4 -4
- data/app/assets/javascripts/tb_core/remote.js +91 -103
- data/app/assets/javascripts/tb_core/utility.js +15 -7
- data/app/assets/libs/rails-ujs.js +705 -0
- data/app/controllers/admin/password_resets_controller.rb +7 -8
- data/app/controllers/password_resets_controller.rb +1 -1
- data/app/controllers/spud/application_controller.rb +2 -1
- data/app/controllers/user_sessions_controller.rb +1 -1
- data/app/views/admin/users/index.html.erb +11 -13
- data/lib/spud_core/version.rb +1 -1
- data/spec/controllers/admin/password_reset_controller_spec.rb +3 -3
- metadata +5 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9b6cb6c8e20c8f5e050ff4194eecd52873a8ee8
|
4
|
+
data.tar.gz: 6f0923c173310c948501ab42f63fd9cdc4117577
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75f1dcb89bd05dad030e06f21955d670c3cd8cb7af2541807de9588840aa1202205699cbd53bb95ecce5d6337ae456fe53b529f01b35e57fcca6c8f83c0ffac0
|
7
|
+
data.tar.gz: e8fbe677701e25eafca66574b35ed73bd0689bddf9af713c896da23d21b28d013a4166f7b7645f450c7bf35917b258e9fb9da0fa149fa0b0649e64c6b0af99ab
|
@@ -15,8 +15,8 @@
|
|
15
15
|
//
|
16
16
|
//= require jquery-ui/core
|
17
17
|
//= require jquery-ui/widget
|
18
|
-
//= require jquery-ui/mouse
|
19
|
-
//= require jquery-ui/draggable
|
20
|
-
//= require jquery-ui/droppable
|
21
|
-
//= require jquery-ui/sortable
|
18
|
+
//= require jquery-ui/widgets/mouse
|
19
|
+
//= require jquery-ui/widgets/draggable
|
20
|
+
//= require jquery-ui/widgets/droppable
|
21
|
+
//= require jquery-ui/widgets/sortable
|
22
22
|
//
|
@@ -1,5 +1,5 @@
|
|
1
|
+
//= require rails-ujs
|
1
2
|
//= require_self
|
2
|
-
//= require jquery_ujs
|
3
3
|
|
4
4
|
(function(){
|
5
5
|
|
@@ -16,14 +16,10 @@
|
|
16
16
|
*/
|
17
17
|
tb.remote = {
|
18
18
|
init: function(){
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
$document.on('ajax:error', 'form[data-errors]', onRemoteFormErrors);
|
24
|
-
$document.on('ajax:success', 'tr a[data-method=delete][data-remote=true]', onRemoteDeleteTableRow);
|
25
|
-
$document.on('ajax:aborted:file', 'form', onRemoteAbortedFile);
|
26
|
-
$document.ready(extendEnableFormElementMethod);
|
19
|
+
Rails.delegate(document, 'form', 'ajax:before', onRemoteFormBefore);
|
20
|
+
Rails.delegate(document, 'form[data-success], a[data-success]', 'ajax:success', onRemoteFormSuccess);
|
21
|
+
Rails.delegate(document, 'form[data-errors]', 'ajax:error', onRemoteFormErrors);
|
22
|
+
Rails.delegate(document, 'tr a[data-method=delete][data-remote=true]', 'ajax:success', onRemoteDeleteTableRow);
|
27
23
|
}
|
28
24
|
};
|
29
25
|
|
@@ -31,22 +27,11 @@ tb.remote = {
|
|
31
27
|
* UJS likes to request application/javascript by default, but Twice Baked prefers JSON.
|
32
28
|
*/
|
33
29
|
var onRemoteFormBefore = function(event){
|
34
|
-
|
35
|
-
|
36
|
-
$form.data('type', 'json');
|
30
|
+
if(this.getAttribute('data-type') === null){
|
31
|
+
this.setAttribute('data-type', 'json');
|
37
32
|
}
|
38
33
|
};
|
39
34
|
|
40
|
-
/*
|
41
|
-
* Runs any time a remote form completes and assigns a true/false value
|
42
|
-
* to lastRemoteSuccess depending on if the post was succesful. This is
|
43
|
-
* referenced later on in enableFormElement
|
44
|
-
*/
|
45
|
-
var onRemoteFormComplete = function(event, jqXHR, textStatus){
|
46
|
-
var success = jqXHR.status >= 200 && jqXHR.status < 300;
|
47
|
-
$(this).data('lastRemoteSuccess', success);
|
48
|
-
};
|
49
|
-
|
50
35
|
/*
|
51
36
|
* Called when a remote form is submitted with a data-success configured
|
52
37
|
* Simply redirects to the configured path, or reloads the page if "reload" is passed
|
@@ -54,12 +39,13 @@ var onRemoteFormComplete = function(event, jqXHR, textStatus){
|
|
54
39
|
* ie:
|
55
40
|
* <form action="..." data-remote="true" data-success="/path/for/success/:id">
|
56
41
|
*/
|
57
|
-
var onRemoteFormSuccess = function(event
|
58
|
-
var successPath =
|
59
|
-
if(successPath
|
42
|
+
var onRemoteFormSuccess = function(event){
|
43
|
+
var successPath = this.getAttribute('data-success');
|
44
|
+
if(successPath === 'reload'){
|
60
45
|
window.location.reload(true);
|
61
46
|
}
|
62
47
|
else{
|
48
|
+
var json = event.detail[0];
|
63
49
|
window.location = buildSuccessPath(successPath, json);
|
64
50
|
}
|
65
51
|
};
|
@@ -94,72 +80,120 @@ var buildSuccessPath = function(path, json){
|
|
94
80
|
* - OR -
|
95
81
|
* <form action="..." data-remote="true" data-errors="alert">
|
96
82
|
*/
|
97
|
-
var onRemoteFormErrors = function(event
|
98
|
-
var
|
99
|
-
var
|
100
|
-
|
101
|
-
|
102
|
-
|
83
|
+
var onRemoteFormErrors = function(event){
|
84
|
+
var json = event.detail[0];
|
85
|
+
var xhr = event.detail[2];
|
86
|
+
var form = this;
|
87
|
+
var errorType = form.getAttribute('data-errors');
|
88
|
+
|
89
|
+
if(xhr.status === 422){
|
90
|
+
if(errorType === 'inline'){
|
91
|
+
tb.remote.displayErrorsInline(form, json);
|
103
92
|
}
|
104
93
|
else{
|
105
|
-
tb.remote.displayErrorsAlert(
|
94
|
+
tb.remote.displayErrorsAlert(json);
|
106
95
|
}
|
107
96
|
}
|
108
|
-
else if(
|
97
|
+
else if(xhr.status === 401 || xhr.status === 403){
|
109
98
|
window.alert('Error: Access denied.');
|
110
99
|
}
|
100
|
+
else if(json.location) {
|
101
|
+
window.location = json.location;
|
102
|
+
}
|
111
103
|
else{
|
104
|
+
var errorThrown = event.detail[1];
|
112
105
|
window.alert('An unexpected error occurred: ' + errorThrown);
|
113
106
|
}
|
114
107
|
};
|
115
108
|
|
109
|
+
function removeElement(element) {
|
110
|
+
element.parentElement.removeChild(element);
|
111
|
+
}
|
112
|
+
|
113
|
+
function createErrorParagraph(text, base) {
|
114
|
+
var p = document.createElement('p');
|
115
|
+
p.classList.add('form-error');
|
116
|
+
p.classList.add(base ? 'form-error-base' : 'form-error-inline');
|
117
|
+
p.innerText = text;
|
118
|
+
return p;
|
119
|
+
}
|
120
|
+
|
121
|
+
function querySelectorArray(parent, selector) {
|
122
|
+
var query = parent.querySelectorAll(selector);
|
123
|
+
var array = Array.prototype.slice.call(query);
|
124
|
+
return array;
|
125
|
+
}
|
126
|
+
|
127
|
+
/*
|
128
|
+
* Take a single error message and format it as if it were
|
129
|
+
* a json error coming from the server
|
130
|
+
*/
|
131
|
+
function formatStringAsErrors(errorString) {
|
132
|
+
return {base: {messages: [errorString] }};
|
133
|
+
}
|
134
|
+
|
135
|
+
/*
|
136
|
+
* Remove inline error messages
|
137
|
+
*/
|
138
|
+
tb.remote.clearErrors = function(form) {
|
139
|
+
querySelectorArray(form, '.form-error-inline, .form-error-base').forEach(removeElement);
|
140
|
+
};
|
141
|
+
|
116
142
|
/*
|
117
143
|
* Append error text to form input fields and scroll to the first error
|
118
144
|
*/
|
119
|
-
tb.remote.displayErrorsInline = function(
|
120
|
-
|
145
|
+
tb.remote.displayErrorsInline = function(form, errors){
|
146
|
+
if(typeof errors === 'string') {
|
147
|
+
errors = formatStringAsErrors(errors);
|
148
|
+
}
|
149
|
+
|
150
|
+
tb.remote.clearErrors(form);
|
151
|
+
|
121
152
|
for(var key in errors){
|
122
153
|
var messages = errors[key].messages;
|
123
|
-
if(key
|
154
|
+
if(key === 'base'){
|
124
155
|
for(var i=0; i<messages.length; i++){
|
125
|
-
|
156
|
+
var p = createErrorParagraph(messages[i], true);
|
157
|
+
form.insertBefore(p, form.firstChild);
|
126
158
|
}
|
127
159
|
}
|
128
160
|
else{
|
129
|
-
var inputName,
|
161
|
+
var inputName, input;
|
130
162
|
|
131
163
|
keyArr = key.split('.');
|
132
164
|
|
133
165
|
if(keyArr.length === 2){
|
134
166
|
keyArr[0] += '_attributes';
|
135
|
-
|
167
|
+
input = form.querySelector("[name$='[" + keyArr.join('][') + "]']");
|
136
168
|
}
|
137
169
|
else{
|
138
|
-
|
170
|
+
var array = querySelectorArray(form, "[name$='[" + key + "]']");
|
171
|
+
input = array.filter(function(input){
|
139
172
|
return !input.name.match(/\]\[/); // Filter out nested attribute inputs ie model[a][b]
|
140
|
-
})
|
141
|
-
if(
|
142
|
-
|
173
|
+
})[0];
|
174
|
+
if(input === null && !key.match(/_id$/)){
|
175
|
+
input = form.querySelector("[name$='[" + key + "_id]']");
|
143
176
|
}
|
144
177
|
}
|
145
178
|
|
146
179
|
var message = messages[0];
|
147
|
-
if(
|
148
|
-
|
180
|
+
if(input){
|
181
|
+
input.parentNode.appendChild(createErrorParagraph(message));
|
149
182
|
}
|
150
183
|
else{
|
151
184
|
console.warn('Missing input field for key:', key);
|
152
|
-
|
185
|
+
form.insertBefore(
|
186
|
+
createErrorParagraph(key+' '+message), form.firstChild
|
187
|
+
);
|
153
188
|
}
|
154
189
|
}
|
155
190
|
}
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
}
|
191
|
+
|
192
|
+
var firstError = form.querySelector('.form-error-inline, .form-error-base')
|
193
|
+
if(firstError &&
|
194
|
+
!tb.util.elementIsInView(firstError) &&
|
195
|
+
typeof(firstError.scrollIntoView) === 'function'){
|
196
|
+
firstError.parentElement.scrollIntoView();
|
163
197
|
}
|
164
198
|
};
|
165
199
|
|
@@ -167,13 +201,16 @@ tb.remote.displayErrorsInline = function($form, errors){
|
|
167
201
|
* Display errors in a standard window.alert dialog
|
168
202
|
*/
|
169
203
|
tb.remote.displayErrorsAlert = function(errors){
|
204
|
+
if(typeof errors === 'string') {
|
205
|
+
errors = formatStringAsErrors(errors);
|
206
|
+
}
|
170
207
|
var text = "Please correct the following errors:\n";
|
171
208
|
var label, message;
|
172
209
|
var index = 0;
|
173
210
|
for(var key in errors){
|
174
211
|
label = errors[key].label;
|
175
212
|
message = errors[key].messages[0];
|
176
|
-
if(key
|
213
|
+
if(key === 'base'){
|
177
214
|
text += ' - ' + message + "\n"
|
178
215
|
}
|
179
216
|
else{
|
@@ -195,55 +232,6 @@ var onRemoteDeleteTableRow = function(){
|
|
195
232
|
});
|
196
233
|
};
|
197
234
|
|
198
|
-
/*
|
199
|
-
* Attach an authenticity_token input field when a remote form aborts due to a file input field
|
200
|
-
*
|
201
|
-
* When a form is configured with remote:true, the authenticity_token hidden input you would normally see is not included. Then what
|
202
|
-
* can happen is the form can fall back to a non-remote action for some reason, possibly due to the presence of a file input field. The
|
203
|
-
* net result is that the server responds with a "Can't verify CSRF token authenticity" error because none was sent.
|
204
|
-
*
|
205
|
-
* This function handles that case by injecting the missing authenticity_token input just before the form is posted.
|
206
|
-
*
|
207
|
-
*/
|
208
|
-
var onRemoteAbortedFile = function(event, inputs){
|
209
|
-
var $form = $(this);
|
210
|
-
var csrfParam = $.rails.csrfParam();
|
211
|
-
if($form.find('input[name='+csrfParam+']').length === 0){
|
212
|
-
var csrfToken = $.rails.csrfToken();
|
213
|
-
var $input = $('<input/>', {
|
214
|
-
type: 'hidden',
|
215
|
-
name: csrfParam,
|
216
|
-
value: csrfToken
|
217
|
-
});
|
218
|
-
$form.prepend($input);
|
219
|
-
}
|
220
|
-
};
|
221
|
-
|
222
|
-
/*
|
223
|
-
* Monkeypatch the base $.rails.enableFormElement function to add a
|
224
|
-
* delay and a success text value to the button before returning to
|
225
|
-
* default state.
|
226
|
-
*/
|
227
|
-
var extendEnableFormElementMethod = function(){
|
228
|
-
var originalEnableFormElement = $.rails.enableFormElement;
|
229
|
-
|
230
|
-
$.rails.enableFormElement = function(element){
|
231
|
-
var success = $(element).parents('form').data('lastRemoteSuccess');
|
232
|
-
var message = element.data('enableWith');
|
233
|
-
|
234
|
-
if(success && message){
|
235
|
-
var method = element.is('button') ? 'html' : 'val';
|
236
|
-
element[method](message);
|
237
|
-
setTimeout(function(){
|
238
|
-
originalEnableFormElement(element);
|
239
|
-
}, 1000);
|
240
|
-
}
|
241
|
-
else{
|
242
|
-
originalEnableFormElement(element);
|
243
|
-
}
|
244
|
-
};
|
245
|
-
};
|
246
|
-
|
247
235
|
tb.remote.init();
|
248
236
|
|
249
237
|
})();
|
@@ -29,18 +29,26 @@ tb.util = {
|
|
29
29
|
},
|
30
30
|
|
31
31
|
getCsrfToken: function(){
|
32
|
-
|
32
|
+
console.warn('Call to tb.util.getCsrfToken() will be removed in the future; Use Rails.csrfToken() instead.')
|
33
|
+
return Rails.csrfToken();
|
33
34
|
},
|
34
35
|
|
35
36
|
/*
|
36
37
|
* Use top/bottom offsets to determine if the given jQuery element is within the current scroll view
|
38
|
+
*
|
39
|
+
* http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/7557433#7557433
|
37
40
|
*/
|
38
|
-
elementIsInView: function(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
elementIsInView: function(el){
|
42
|
+
if (typeof jQuery === "function" && el instanceof jQuery) {
|
43
|
+
el = el[0];
|
44
|
+
}
|
45
|
+
var rect = el.getBoundingClientRect();
|
46
|
+
return (
|
47
|
+
rect.top >= 0 &&
|
48
|
+
rect.left >= 0 &&
|
49
|
+
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
|
50
|
+
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
|
51
|
+
);
|
44
52
|
}
|
45
53
|
};
|
46
54
|
|
@@ -0,0 +1,705 @@
|
|
1
|
+
// https://github.com/rails/rails-ujs
|
2
|
+
|
3
|
+
(function() {
|
4
|
+
(function() {
|
5
|
+
(function() {
|
6
|
+
this.Rails = {
|
7
|
+
linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]',
|
8
|
+
buttonClickSelector: {
|
9
|
+
selector: 'button[data-remote]:not([form]), button[data-confirm]:not([form])',
|
10
|
+
exclude: 'form button'
|
11
|
+
},
|
12
|
+
inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
|
13
|
+
formSubmitSelector: 'form',
|
14
|
+
formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
|
15
|
+
formDisableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
|
16
|
+
formEnableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled',
|
17
|
+
requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])',
|
18
|
+
fileInputSelector: 'input[name][type=file]:not([disabled])',
|
19
|
+
linkDisableSelector: 'a[data-disable-with], a[data-disable]',
|
20
|
+
buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]'
|
21
|
+
};
|
22
|
+
|
23
|
+
}).call(this);
|
24
|
+
}).call(this);
|
25
|
+
|
26
|
+
var Rails = this.Rails;
|
27
|
+
|
28
|
+
(function() {
|
29
|
+
(function() {
|
30
|
+
var expando, m;
|
31
|
+
|
32
|
+
m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector;
|
33
|
+
|
34
|
+
Rails.matches = function(element, selector) {
|
35
|
+
if (selector.exclude != null) {
|
36
|
+
return m.call(element, selector.selector) && !m.call(element, selector.exclude);
|
37
|
+
} else {
|
38
|
+
return m.call(element, selector);
|
39
|
+
}
|
40
|
+
};
|
41
|
+
|
42
|
+
expando = '_ujsData';
|
43
|
+
|
44
|
+
Rails.getData = function(element, key) {
|
45
|
+
var ref;
|
46
|
+
return (ref = element[expando]) != null ? ref[key] : void 0;
|
47
|
+
};
|
48
|
+
|
49
|
+
Rails.setData = function(element, key, value) {
|
50
|
+
if (element[expando] == null) {
|
51
|
+
element[expando] = {};
|
52
|
+
}
|
53
|
+
return element[expando][key] = value;
|
54
|
+
};
|
55
|
+
|
56
|
+
Rails.$ = function(selector) {
|
57
|
+
return Array.prototype.slice.call(document.querySelectorAll(selector));
|
58
|
+
};
|
59
|
+
|
60
|
+
}).call(this);
|
61
|
+
(function() {
|
62
|
+
var $, csrfParam, csrfToken;
|
63
|
+
|
64
|
+
$ = Rails.$;
|
65
|
+
|
66
|
+
csrfToken = Rails.csrfToken = function() {
|
67
|
+
var meta;
|
68
|
+
meta = document.querySelector('meta[name=csrf-token]');
|
69
|
+
return meta && meta.content;
|
70
|
+
};
|
71
|
+
|
72
|
+
csrfParam = Rails.csrfParam = function() {
|
73
|
+
var meta;
|
74
|
+
meta = document.querySelector('meta[name=csrf-param]');
|
75
|
+
return meta && meta.content;
|
76
|
+
};
|
77
|
+
|
78
|
+
Rails.CSRFProtection = function(xhr) {
|
79
|
+
var token;
|
80
|
+
token = csrfToken();
|
81
|
+
if (token != null) {
|
82
|
+
return xhr.setRequestHeader('X-CSRF-Token', token);
|
83
|
+
}
|
84
|
+
};
|
85
|
+
|
86
|
+
Rails.refreshCSRFTokens = function() {
|
87
|
+
var param, token;
|
88
|
+
token = csrfToken();
|
89
|
+
param = csrfParam();
|
90
|
+
if ((token != null) && (param != null)) {
|
91
|
+
return $('form input[name="' + param + '"]').forEach(function(input) {
|
92
|
+
return input.value = token;
|
93
|
+
});
|
94
|
+
}
|
95
|
+
};
|
96
|
+
|
97
|
+
}).call(this);
|
98
|
+
(function() {
|
99
|
+
var CustomEvent, fire, matches;
|
100
|
+
|
101
|
+
matches = Rails.matches;
|
102
|
+
|
103
|
+
CustomEvent = window.CustomEvent;
|
104
|
+
|
105
|
+
if (typeof CustomEvent === 'function') {
|
106
|
+
CustomEvent = function(event, params) {
|
107
|
+
var evt;
|
108
|
+
evt = document.createEvent('CustomEvent');
|
109
|
+
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
110
|
+
return evt;
|
111
|
+
};
|
112
|
+
CustomEvent.prototype = window.Event.prototype;
|
113
|
+
}
|
114
|
+
|
115
|
+
fire = Rails.fire = function(obj, name, data) {
|
116
|
+
var event;
|
117
|
+
event = new CustomEvent(name, {
|
118
|
+
bubbles: true,
|
119
|
+
cancelable: true,
|
120
|
+
detail: data
|
121
|
+
});
|
122
|
+
obj.dispatchEvent(event);
|
123
|
+
return !event.defaultPrevented;
|
124
|
+
};
|
125
|
+
|
126
|
+
Rails.stopEverything = function(e) {
|
127
|
+
fire(e.target, 'ujs:everythingStopped');
|
128
|
+
e.preventDefault();
|
129
|
+
e.stopPropagation();
|
130
|
+
return e.stopImmediatePropagation();
|
131
|
+
};
|
132
|
+
|
133
|
+
Rails.delegate = function(element, selector, eventType, handler) {
|
134
|
+
return element.addEventListener(eventType, function(e) {
|
135
|
+
var target;
|
136
|
+
target = e.target;
|
137
|
+
while (!(!(target instanceof Element) || matches(target, selector))) {
|
138
|
+
target = target.parentNode;
|
139
|
+
}
|
140
|
+
if (target instanceof Element && handler.call(target, e) === false) {
|
141
|
+
e.preventDefault();
|
142
|
+
return e.stopPropagation();
|
143
|
+
}
|
144
|
+
});
|
145
|
+
};
|
146
|
+
|
147
|
+
}).call(this);
|
148
|
+
(function() {
|
149
|
+
var AcceptHeaders, CSRFProtection, createXHR, fire, prepareOptions, processResponse;
|
150
|
+
|
151
|
+
CSRFProtection = Rails.CSRFProtection, fire = Rails.fire;
|
152
|
+
|
153
|
+
AcceptHeaders = {
|
154
|
+
'*': '*/*',
|
155
|
+
text: 'text/plain',
|
156
|
+
html: 'text/html',
|
157
|
+
xml: 'application/xml, text/xml',
|
158
|
+
json: 'application/json, text/javascript',
|
159
|
+
script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'
|
160
|
+
};
|
161
|
+
|
162
|
+
Rails.ajax = function(options) {
|
163
|
+
var xhr;
|
164
|
+
options = prepareOptions(options);
|
165
|
+
xhr = createXHR(options, function() {
|
166
|
+
var response;
|
167
|
+
response = processResponse(xhr.response, xhr.getResponseHeader('Content-Type'));
|
168
|
+
if (Math.floor(xhr.status / 100) === 2) {
|
169
|
+
if (typeof options.success === "function") {
|
170
|
+
options.success(response, xhr.statusText, xhr);
|
171
|
+
}
|
172
|
+
} else {
|
173
|
+
if (typeof options.error === "function") {
|
174
|
+
options.error(response, xhr.statusText, xhr);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
return typeof options.complete === "function" ? options.complete(xhr, xhr.statusText) : void 0;
|
178
|
+
});
|
179
|
+
if (typeof options.beforeSend === "function") {
|
180
|
+
options.beforeSend(xhr, options);
|
181
|
+
}
|
182
|
+
if (xhr.readyState === XMLHttpRequest.OPENED) {
|
183
|
+
return xhr.send(options.data);
|
184
|
+
} else {
|
185
|
+
return fire(document, 'ajaxStop');
|
186
|
+
}
|
187
|
+
};
|
188
|
+
|
189
|
+
prepareOptions = function(options) {
|
190
|
+
options.type = options.type.toUpperCase();
|
191
|
+
if (options.type === 'GET' && options.data) {
|
192
|
+
if (options.url.indexOf('?') < 0) {
|
193
|
+
options.url += '?' + options.data;
|
194
|
+
} else {
|
195
|
+
options.url += '&' + options.data;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
if (AcceptHeaders[options.dataType] == null) {
|
199
|
+
options.dataType = '*';
|
200
|
+
}
|
201
|
+
options.accept = AcceptHeaders[options.dataType];
|
202
|
+
if (options.dataType !== '*') {
|
203
|
+
options.accept += ', */*; q=0.01';
|
204
|
+
}
|
205
|
+
return options;
|
206
|
+
};
|
207
|
+
|
208
|
+
createXHR = function(options, done) {
|
209
|
+
var xhr;
|
210
|
+
xhr = new XMLHttpRequest();
|
211
|
+
xhr.open(options.type, options.url, true);
|
212
|
+
xhr.setRequestHeader('Accept', options.accept);
|
213
|
+
if (typeof options.data === 'string') {
|
214
|
+
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
215
|
+
}
|
216
|
+
if (!options.crossDomain) {
|
217
|
+
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
218
|
+
}
|
219
|
+
CSRFProtection(xhr);
|
220
|
+
xhr.withCredentials = !!options.withCredentials;
|
221
|
+
xhr.onreadystatechange = function() {
|
222
|
+
if (xhr.readyState === XMLHttpRequest.DONE) {
|
223
|
+
return done(xhr);
|
224
|
+
}
|
225
|
+
};
|
226
|
+
return xhr;
|
227
|
+
};
|
228
|
+
|
229
|
+
processResponse = function(response, type) {
|
230
|
+
var parser, script;
|
231
|
+
if (typeof response === 'string' && typeof type === 'string') {
|
232
|
+
if (type.match(/\bjson\b/)) {
|
233
|
+
try {
|
234
|
+
response = JSON.parse(response);
|
235
|
+
} catch (undefined) {}
|
236
|
+
} else if (type.match(/\bjavascript\b/)) {
|
237
|
+
script = document.createElement('script');
|
238
|
+
script.innerHTML = response;
|
239
|
+
document.body.appendChild(script);
|
240
|
+
} else if (type.match(/\b(xml|html|svg)\b/)) {
|
241
|
+
parser = new DOMParser();
|
242
|
+
type = type.replace(/;.+/, '');
|
243
|
+
try {
|
244
|
+
response = parser.parseFromString(response, type);
|
245
|
+
} catch (undefined) {}
|
246
|
+
}
|
247
|
+
}
|
248
|
+
return response;
|
249
|
+
};
|
250
|
+
|
251
|
+
Rails.href = function(element) {
|
252
|
+
return element.href;
|
253
|
+
};
|
254
|
+
|
255
|
+
Rails.isCrossDomain = function(url) {
|
256
|
+
var e, error, originAnchor, urlAnchor;
|
257
|
+
originAnchor = document.createElement('a');
|
258
|
+
originAnchor.href = location.href;
|
259
|
+
urlAnchor = document.createElement('a');
|
260
|
+
try {
|
261
|
+
urlAnchor.href = url;
|
262
|
+
return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) || (originAnchor.protocol + '//' + originAnchor.host === urlAnchor.protocol + '//' + urlAnchor.host));
|
263
|
+
} catch (error) {
|
264
|
+
e = error;
|
265
|
+
return true;
|
266
|
+
}
|
267
|
+
};
|
268
|
+
|
269
|
+
}).call(this);
|
270
|
+
(function() {
|
271
|
+
var matches, toArray;
|
272
|
+
|
273
|
+
matches = Rails.matches;
|
274
|
+
|
275
|
+
toArray = function(e) {
|
276
|
+
return Array.prototype.slice.call(e);
|
277
|
+
};
|
278
|
+
|
279
|
+
Rails.serializeElement = function(element, additionalParam) {
|
280
|
+
var inputs, params;
|
281
|
+
inputs = [element];
|
282
|
+
if (matches(element, 'form')) {
|
283
|
+
inputs = toArray(element.elements);
|
284
|
+
}
|
285
|
+
params = [];
|
286
|
+
inputs.forEach(function(input) {
|
287
|
+
if (!input.name) {
|
288
|
+
return;
|
289
|
+
}
|
290
|
+
if (matches(input, 'select')) {
|
291
|
+
return toArray(input.options).forEach(function(option) {
|
292
|
+
if (option.selected) {
|
293
|
+
return params.push({
|
294
|
+
name: input.name,
|
295
|
+
value: option.value
|
296
|
+
});
|
297
|
+
}
|
298
|
+
});
|
299
|
+
} else if (input.type !== 'radio' && input.type !== 'checkbox' || input.checked) {
|
300
|
+
return params.push({
|
301
|
+
name: input.name,
|
302
|
+
value: input.value
|
303
|
+
});
|
304
|
+
}
|
305
|
+
});
|
306
|
+
if (additionalParam) {
|
307
|
+
params.push(additionalParam);
|
308
|
+
}
|
309
|
+
return params.map(function(param) {
|
310
|
+
if (param.name != null) {
|
311
|
+
return (encodeURIComponent(param.name)) + "=" + (encodeURIComponent(param.value));
|
312
|
+
} else {
|
313
|
+
return param;
|
314
|
+
}
|
315
|
+
}).join('&');
|
316
|
+
};
|
317
|
+
|
318
|
+
Rails.formElements = function(form, selector) {
|
319
|
+
if (matches(form, 'form')) {
|
320
|
+
return toArray(form.elements).filter(function(el) {
|
321
|
+
return matches(el, selector);
|
322
|
+
});
|
323
|
+
} else {
|
324
|
+
return toArray(form.querySelectorAll(selector));
|
325
|
+
}
|
326
|
+
};
|
327
|
+
|
328
|
+
Rails.blankInputs = function(form, selector, nonBlank) {
|
329
|
+
var checkedRadioButtonNames, foundInputs, requiredInputs;
|
330
|
+
foundInputs = [];
|
331
|
+
requiredInputs = toArray(form.querySelectorAll(selector || 'input, textarea'));
|
332
|
+
checkedRadioButtonNames = {};
|
333
|
+
requiredInputs.forEach(function(input) {
|
334
|
+
var radioName, radios, valueToCheck;
|
335
|
+
if (input.type === 'radio') {
|
336
|
+
radioName = input.name;
|
337
|
+
if (!checkedRadioButtonNames[radioName]) {
|
338
|
+
if (form.querySelectorAll("input[type=radio][name='" + radioName + "']:checked").length === 0) {
|
339
|
+
radios = form.querySelectorAll("input[type=radio][name='" + radioName + "']");
|
340
|
+
foundInputs = foundInputs.concat(toArray(radios));
|
341
|
+
}
|
342
|
+
return checkedRadioButtonNames[radioName] = radioName;
|
343
|
+
}
|
344
|
+
} else {
|
345
|
+
valueToCheck = input.type === 'checkbox' ? input.checked : !!input.value;
|
346
|
+
if (valueToCheck === nonBlank) {
|
347
|
+
return foundInputs.push(input);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
});
|
351
|
+
return foundInputs;
|
352
|
+
};
|
353
|
+
|
354
|
+
}).call(this);
|
355
|
+
(function() {
|
356
|
+
var allowAction, fire, stopEverything;
|
357
|
+
|
358
|
+
fire = Rails.fire, stopEverything = Rails.stopEverything;
|
359
|
+
|
360
|
+
Rails.handleConfirm = function(e) {
|
361
|
+
if (!allowAction(this)) {
|
362
|
+
return stopEverything(e);
|
363
|
+
}
|
364
|
+
};
|
365
|
+
|
366
|
+
allowAction = function(element) {
|
367
|
+
var answer, callback, message;
|
368
|
+
message = element.getAttribute('data-confirm');
|
369
|
+
if (!message) {
|
370
|
+
return true;
|
371
|
+
}
|
372
|
+
answer = false;
|
373
|
+
if (fire(element, 'confirm')) {
|
374
|
+
try {
|
375
|
+
answer = confirm(message);
|
376
|
+
} catch (undefined) {}
|
377
|
+
callback = fire(element, 'confirm:complete', [answer]);
|
378
|
+
}
|
379
|
+
return answer && callback;
|
380
|
+
};
|
381
|
+
|
382
|
+
}).call(this);
|
383
|
+
(function() {
|
384
|
+
var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, matches, setData, stopEverything;
|
385
|
+
|
386
|
+
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements;
|
387
|
+
|
388
|
+
Rails.enableElement = function(e) {
|
389
|
+
var element;
|
390
|
+
element = e instanceof Event ? e.target : e;
|
391
|
+
if (matches(element, Rails.linkDisableSelector)) {
|
392
|
+
return enableLinkElement(element);
|
393
|
+
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) {
|
394
|
+
return enableFormElement(element);
|
395
|
+
} else if (matches(element, Rails.formSubmitSelector)) {
|
396
|
+
return enableFormElements(element);
|
397
|
+
}
|
398
|
+
};
|
399
|
+
|
400
|
+
Rails.disableElement = function(e) {
|
401
|
+
var element;
|
402
|
+
element = e instanceof Event ? e.target : e;
|
403
|
+
if (matches(element, Rails.linkDisableSelector)) {
|
404
|
+
return disableLinkElement(element);
|
405
|
+
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) {
|
406
|
+
return disableFormElement(element);
|
407
|
+
} else if (matches(element, Rails.formSubmitSelector)) {
|
408
|
+
return disableFormElements(element);
|
409
|
+
}
|
410
|
+
};
|
411
|
+
|
412
|
+
disableLinkElement = function(element) {
|
413
|
+
var replacement;
|
414
|
+
replacement = element.getAttribute('data-disable-with');
|
415
|
+
if (replacement != null) {
|
416
|
+
setData(element, 'ujs:enable-with', element.innerHTML);
|
417
|
+
element.innerHTML = replacement;
|
418
|
+
}
|
419
|
+
element.addEventListener('click', stopEverything);
|
420
|
+
return setData(element, 'ujs:disabled', true);
|
421
|
+
};
|
422
|
+
|
423
|
+
enableLinkElement = function(element) {
|
424
|
+
var originalText;
|
425
|
+
originalText = getData(element, 'ujs:enable-with');
|
426
|
+
if (originalText != null) {
|
427
|
+
element.innerHTML = originalText;
|
428
|
+
setData(element, 'ujs:enable-with', null);
|
429
|
+
}
|
430
|
+
element.removeEventListener('click', stopEverything);
|
431
|
+
return setData(element, 'ujs:disabled', null);
|
432
|
+
};
|
433
|
+
|
434
|
+
disableFormElements = function(form) {
|
435
|
+
return formElements(form, Rails.formDisableSelector).forEach(disableFormElement);
|
436
|
+
};
|
437
|
+
|
438
|
+
disableFormElement = function(element) {
|
439
|
+
var replacement;
|
440
|
+
replacement = element.getAttribute('data-disable-with');
|
441
|
+
if (replacement != null) {
|
442
|
+
if (matches(element, 'button')) {
|
443
|
+
setData(element, 'ujs:enable-with', element.innerHTML);
|
444
|
+
element.innerHTML = replacement;
|
445
|
+
} else {
|
446
|
+
setData(element, 'ujs:enable-with', element.value);
|
447
|
+
element.value = replacement;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
element.disabled = true;
|
451
|
+
return setData(element, 'ujs:disabled', true);
|
452
|
+
};
|
453
|
+
|
454
|
+
enableFormElements = function(form) {
|
455
|
+
return formElements(form, Rails.formEnableSelector).forEach(enableFormElement);
|
456
|
+
};
|
457
|
+
|
458
|
+
enableFormElement = function(element) {
|
459
|
+
var originalText;
|
460
|
+
originalText = getData(element, 'ujs:enable-with');
|
461
|
+
if (originalText != null) {
|
462
|
+
if (matches(element, 'button')) {
|
463
|
+
element.innerHTML = originalText;
|
464
|
+
} else {
|
465
|
+
element.value = originalText;
|
466
|
+
}
|
467
|
+
setData(element, 'ujs:enable-with', null);
|
468
|
+
}
|
469
|
+
element.disabled = false;
|
470
|
+
return setData(element, 'ujs:disabled', null);
|
471
|
+
};
|
472
|
+
|
473
|
+
}).call(this);
|
474
|
+
(function() {
|
475
|
+
var stopEverything;
|
476
|
+
|
477
|
+
stopEverything = Rails.stopEverything;
|
478
|
+
|
479
|
+
Rails.handleMethod = function(e) {
|
480
|
+
var csrfParam, csrfToken, form, formContent, href, link, method;
|
481
|
+
link = this;
|
482
|
+
method = link.getAttribute('data-method');
|
483
|
+
if (!method) {
|
484
|
+
return;
|
485
|
+
}
|
486
|
+
href = Rails.href(link);
|
487
|
+
csrfToken = Rails.csrfToken();
|
488
|
+
csrfParam = Rails.csrfParam();
|
489
|
+
form = document.createElement('form');
|
490
|
+
formContent = "<input name='_method' value='" + method + "' type='hidden' />";
|
491
|
+
if ((csrfParam != null) && (csrfToken != null) && !Rails.isCrossDomain(href)) {
|
492
|
+
formContent += "<input name='" + csrfParam + "' value='" + csrfToken + "' type='hidden' />";
|
493
|
+
}
|
494
|
+
formContent += '<input type="submit" />';
|
495
|
+
form.method = 'post';
|
496
|
+
form.action = href;
|
497
|
+
form.target = link.target;
|
498
|
+
form.innerHTML = formContent;
|
499
|
+
form.style.display = 'none';
|
500
|
+
document.body.appendChild(form);
|
501
|
+
form.querySelector('[type="submit"]').click();
|
502
|
+
return stopEverything(e);
|
503
|
+
};
|
504
|
+
|
505
|
+
}).call(this);
|
506
|
+
(function() {
|
507
|
+
var ajax, blankInputs, fire, getData, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything,
|
508
|
+
slice = [].slice;
|
509
|
+
|
510
|
+
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, blankInputs = Rails.blankInputs, serializeElement = Rails.serializeElement;
|
511
|
+
|
512
|
+
isRemote = function(element) {
|
513
|
+
var value;
|
514
|
+
value = element.getAttribute('data-remote');
|
515
|
+
return (value != null) && value !== 'false';
|
516
|
+
};
|
517
|
+
|
518
|
+
Rails.handleRemote = function(e) {
|
519
|
+
var button, data, dataType, element, method, url, withCredentials;
|
520
|
+
element = this;
|
521
|
+
if (!isRemote(element)) {
|
522
|
+
return true;
|
523
|
+
}
|
524
|
+
if (!fire(element, 'ajax:before')) {
|
525
|
+
fire(element, 'ajax:stopped');
|
526
|
+
return false;
|
527
|
+
}
|
528
|
+
withCredentials = element.getAttribute('data-with-credentials');
|
529
|
+
dataType = element.getAttribute('data-type') || 'script';
|
530
|
+
if (matches(element, Rails.formSubmitSelector)) {
|
531
|
+
button = getData(element, 'ujs:submit-button');
|
532
|
+
method = getData(element, 'ujs:submit-button-formmethod') || element.method;
|
533
|
+
url = getData(element, 'ujs:submit-button-formaction') || element.getAttribute('action') || location.href;
|
534
|
+
if (method.toUpperCase() === 'GET') {
|
535
|
+
url = url.replace(/\?.*$/, '');
|
536
|
+
}
|
537
|
+
if (element.enctype === 'multipart/form-data') {
|
538
|
+
data = new FormData(element);
|
539
|
+
if (button != null) {
|
540
|
+
data.append(button.name, button.value);
|
541
|
+
}
|
542
|
+
} else {
|
543
|
+
data = serializeElement(element, button);
|
544
|
+
}
|
545
|
+
setData(element, 'ujs:submit-button', null);
|
546
|
+
setData(element, 'ujs:submit-button-formmethod', null);
|
547
|
+
setData(element, 'ujs:submit-button-formaction', null);
|
548
|
+
} else if (matches(element, Rails.buttonClickSelector) || matches(element, Rails.inputChangeSelector)) {
|
549
|
+
method = element.getAttribute('data-method');
|
550
|
+
url = element.getAttribute('data-url');
|
551
|
+
data = serializeElement(element, element.getAttribute('data-params'));
|
552
|
+
} else {
|
553
|
+
method = element.getAttribute('data-method');
|
554
|
+
url = Rails.href(element);
|
555
|
+
data = element.getAttribute('data-params');
|
556
|
+
}
|
557
|
+
ajax({
|
558
|
+
type: method || 'GET',
|
559
|
+
url: url,
|
560
|
+
data: data,
|
561
|
+
dataType: dataType,
|
562
|
+
beforeSend: function(xhr, options) {
|
563
|
+
if (fire(element, 'ajax:beforeSend', [xhr, options])) {
|
564
|
+
return fire(element, 'ajax:send', [xhr]);
|
565
|
+
} else {
|
566
|
+
fire(element, 'ajax:stopped');
|
567
|
+
return xhr.abort();
|
568
|
+
}
|
569
|
+
},
|
570
|
+
success: function() {
|
571
|
+
var args;
|
572
|
+
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
573
|
+
return fire(element, 'ajax:success', args);
|
574
|
+
},
|
575
|
+
error: function() {
|
576
|
+
var args;
|
577
|
+
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
578
|
+
return fire(element, 'ajax:error', args);
|
579
|
+
},
|
580
|
+
complete: function() {
|
581
|
+
var args;
|
582
|
+
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
583
|
+
return fire(element, 'ajax:complete', args);
|
584
|
+
},
|
585
|
+
crossDomain: isCrossDomain(url),
|
586
|
+
withCredentials: (withCredentials != null) && withCredentials !== 'false'
|
587
|
+
});
|
588
|
+
return stopEverything(e);
|
589
|
+
};
|
590
|
+
|
591
|
+
Rails.validateForm = function(e) {
|
592
|
+
var blankRequiredInputs, form;
|
593
|
+
form = this;
|
594
|
+
if (form.noValidate || getData(form, 'ujs:formnovalidate-button')) {
|
595
|
+
return;
|
596
|
+
}
|
597
|
+
blankRequiredInputs = blankInputs(form, Rails.requiredInputSelector, false);
|
598
|
+
if (blankRequiredInputs.length > 0 && fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
|
599
|
+
return stopEverything(e);
|
600
|
+
}
|
601
|
+
};
|
602
|
+
|
603
|
+
Rails.formSubmitButtonClick = function(e) {
|
604
|
+
var button, form;
|
605
|
+
button = this;
|
606
|
+
form = button.form;
|
607
|
+
if (!form) {
|
608
|
+
return;
|
609
|
+
}
|
610
|
+
if (button.name) {
|
611
|
+
setData(form, 'ujs:submit-button', {
|
612
|
+
name: button.name,
|
613
|
+
value: button.value
|
614
|
+
});
|
615
|
+
}
|
616
|
+
setData(form, 'ujs:formnovalidate-button', button.formNoValidate);
|
617
|
+
setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction'));
|
618
|
+
return setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod'));
|
619
|
+
};
|
620
|
+
|
621
|
+
Rails.handleMetaClick = function(e) {
|
622
|
+
var data, link, metaClick, method;
|
623
|
+
link = this;
|
624
|
+
method = (link.getAttribute('data-method') || 'GET').toUpperCase();
|
625
|
+
data = link.getAttribute('data-params');
|
626
|
+
metaClick = e.metaKey || e.ctrlKey;
|
627
|
+
if (metaClick && method === 'GET' && !data) {
|
628
|
+
return e.stopImmediatePropagation();
|
629
|
+
}
|
630
|
+
};
|
631
|
+
|
632
|
+
}).call(this);
|
633
|
+
(function() {
|
634
|
+
var $, CSRFProtection, delegate, disableElement, enableElement, fire, formSubmitButtonClick, getData, handleConfirm, handleMetaClick, handleMethod, handleRemote, refreshCSRFTokens, validateForm;
|
635
|
+
|
636
|
+
fire = Rails.fire, delegate = Rails.delegate, getData = Rails.getData, $ = Rails.$, refreshCSRFTokens = Rails.refreshCSRFTokens, CSRFProtection = Rails.CSRFProtection, enableElement = Rails.enableElement, disableElement = Rails.disableElement, handleConfirm = Rails.handleConfirm, handleRemote = Rails.handleRemote, validateForm = Rails.validateForm, formSubmitButtonClick = Rails.formSubmitButtonClick, handleMetaClick = Rails.handleMetaClick, handleMethod = Rails.handleMethod;
|
637
|
+
|
638
|
+
if ((typeof jQuery !== "undefined" && jQuery !== null) && !jQuery.rails) {
|
639
|
+
jQuery.rails = Rails;
|
640
|
+
jQuery.ajaxPrefilter(function(options, originalOptions, xhr) {
|
641
|
+
if (!options.crossDomain) {
|
642
|
+
return CSRFProtection(xhr);
|
643
|
+
}
|
644
|
+
});
|
645
|
+
}
|
646
|
+
|
647
|
+
Rails.start = function() {
|
648
|
+
if (window._rails_loaded) {
|
649
|
+
throw new Error('jquery-ujs has already been loaded!');
|
650
|
+
}
|
651
|
+
window.addEventListener('pageshow', function() {
|
652
|
+
$(Rails.formEnableSelector).forEach(function(el) {
|
653
|
+
if (getData(el, 'ujs:disabled')) {
|
654
|
+
return enableElement(el);
|
655
|
+
}
|
656
|
+
});
|
657
|
+
return $(Rails.linkDisableSelector).forEach(function(el) {
|
658
|
+
if (getData(el, 'ujs:disabled')) {
|
659
|
+
return enableElement(el);
|
660
|
+
}
|
661
|
+
});
|
662
|
+
});
|
663
|
+
delegate(document, Rails.linkDisableSelector, 'ajax:complete', enableElement);
|
664
|
+
delegate(document, Rails.linkDisableSelector, 'ajax:stopped', enableElement);
|
665
|
+
delegate(document, Rails.buttonDisableSelector, 'ajax:complete', enableElement);
|
666
|
+
delegate(document, Rails.buttonDisableSelector, 'ajax:stopped', enableElement);
|
667
|
+
delegate(document, Rails.linkClickSelector, 'click', handleConfirm);
|
668
|
+
delegate(document, Rails.linkClickSelector, 'click', handleMetaClick);
|
669
|
+
delegate(document, Rails.linkClickSelector, 'click', disableElement);
|
670
|
+
delegate(document, Rails.linkClickSelector, 'click', handleRemote);
|
671
|
+
delegate(document, Rails.linkClickSelector, 'click', handleMethod);
|
672
|
+
delegate(document, Rails.buttonClickSelector, 'click', handleConfirm);
|
673
|
+
delegate(document, Rails.buttonClickSelector, 'click', disableElement);
|
674
|
+
delegate(document, Rails.buttonClickSelector, 'click', handleRemote);
|
675
|
+
delegate(document, Rails.inputChangeSelector, 'change', handleConfirm);
|
676
|
+
delegate(document, Rails.inputChangeSelector, 'change', handleRemote);
|
677
|
+
delegate(document, Rails.formSubmitSelector, 'submit', handleConfirm);
|
678
|
+
delegate(document, Rails.formSubmitSelector, 'submit', validateForm);
|
679
|
+
delegate(document, Rails.formSubmitSelector, 'submit', handleRemote);
|
680
|
+
delegate(document, Rails.formSubmitSelector, 'submit', function(e) {
|
681
|
+
return setTimeout((function() {
|
682
|
+
return disableElement(e);
|
683
|
+
}), 13);
|
684
|
+
});
|
685
|
+
delegate(document, Rails.formSubmitSelector, 'ajax:send', disableElement);
|
686
|
+
delegate(document, Rails.formSubmitSelector, 'ajax:complete', enableElement);
|
687
|
+
delegate(document, Rails.formInputClickSelector, 'click', handleConfirm);
|
688
|
+
delegate(document, Rails.formInputClickSelector, 'click', formSubmitButtonClick);
|
689
|
+
document.addEventListener('DOMContentLoaded', refreshCSRFTokens);
|
690
|
+
return window._rails_loaded = true;
|
691
|
+
};
|
692
|
+
|
693
|
+
if (window.Rails === Rails && fire(document, 'rails:attachBindings')) {
|
694
|
+
Rails.start();
|
695
|
+
}
|
696
|
+
|
697
|
+
}).call(this);
|
698
|
+
}).call(this);
|
699
|
+
|
700
|
+
if (typeof module === "object" && module.exports) {
|
701
|
+
module.exports = Rails;
|
702
|
+
} else if (typeof define === "function" && define.amd) {
|
703
|
+
define(Rails);
|
704
|
+
}
|
705
|
+
}).call(this);
|
@@ -9,7 +9,7 @@ class Admin::PasswordResetsController < Admin::ApplicationController
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create
|
12
|
-
@user = SpudUser.
|
12
|
+
@user = SpudUser.find_by(email: params[:email])
|
13
13
|
if @user
|
14
14
|
@user.reset_perishable_token!
|
15
15
|
TbCoreMailer.forgot_password_notification(@user, admin_password_reset_url(@user.perishable_token)).deliver_later
|
@@ -42,12 +42,11 @@ private
|
|
42
42
|
|
43
43
|
def load_user_using_perishable_token
|
44
44
|
@user = SpudUser.find_using_perishable_token(params[:id])
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
45
|
+
return if @user
|
46
|
+
flash[:notice] = "We're sorry, but we could not locate your account. " +
|
47
|
+
'If you are having issues try copying and pasting the URL ' +
|
48
|
+
'from your email into your browser or restarting the ' +
|
49
|
+
'reset password process.'
|
50
|
+
redirect_to admin_login_path
|
52
51
|
end
|
53
52
|
end
|
@@ -10,7 +10,7 @@ class PasswordResetsController < ApplicationController
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def create
|
13
|
-
@user = SpudUser.
|
13
|
+
@user = SpudUser.find_by(email: params[:email])
|
14
14
|
if @user
|
15
15
|
@user.reset_perishable_token!
|
16
16
|
TbCoreMailer.forgot_password_notification(@user, password_reset_url(@user.perishable_token)).deliver_later
|
@@ -52,7 +52,7 @@ private
|
|
52
52
|
# Override this in a controller to redifine where the login form is
|
53
53
|
#
|
54
54
|
def login_path_for_require_user
|
55
|
-
login_path(return_to: request.
|
55
|
+
login_path(return_to: request.fullpath)
|
56
56
|
end
|
57
57
|
|
58
58
|
def require_admin_user
|
@@ -70,6 +70,7 @@ private
|
|
70
70
|
def back_or_default(default='/')
|
71
71
|
if params[:return_to]
|
72
72
|
uri = URI.parse(params[:return_to].to_s)
|
73
|
+
return "#{uri.path}?#{uri.query}" if uri.query
|
73
74
|
return uri.path
|
74
75
|
else
|
75
76
|
return default
|
@@ -65,7 +65,7 @@ class UserSessionsController < ApplicationController
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def user_session_params
|
68
|
-
params.require(:spud_user_session).permit(:login, :password)
|
68
|
+
params.require(:spud_user_session).permit(:login, :password, :email)
|
69
69
|
end
|
70
70
|
|
71
71
|
def change_password_params
|
@@ -15,19 +15,17 @@
|
|
15
15
|
<th> </th>
|
16
16
|
</thead>
|
17
17
|
<tbody>
|
18
|
-
<%
|
19
|
-
|
20
|
-
<
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
</tr>
|
30
|
-
<% end %>
|
18
|
+
<% @spud_users.each do |spud_user| %>
|
19
|
+
<tr>
|
20
|
+
<td><%= spud_user.full_name %></td>
|
21
|
+
<td><%= mail_to spud_user.email %></td>
|
22
|
+
<td><%= timestamp(spud_user.current_login_at) %></td>
|
23
|
+
<td class="table-actions">
|
24
|
+
<%= link_to 'Details', admin_user_path(spud_user), :class => 'btn btn-default btn-sm' %>
|
25
|
+
<%= link_to 'Edit', edit_admin_user_path(spud_user), :class => 'btn btn-default btn-sm' %>
|
26
|
+
<%= link_to 'Delete', admin_user_path(spud_user), :method => :delete, :data => {:confirm => 'Are you sure you want to delete this user?'}, :class => 'btn btn-danger btn-sm' %>
|
27
|
+
</td>
|
28
|
+
</tr>
|
31
29
|
<% end %>
|
32
30
|
</tbody>
|
33
31
|
</table>
|
data/lib/spud_core/version.rb
CHANGED
@@ -36,14 +36,14 @@ describe Admin::PasswordResetsController, type: :controller do
|
|
36
36
|
describe 'create' do
|
37
37
|
context 'with a valid user email address submitted' do
|
38
38
|
it 'should trigger the password notificiation' do
|
39
|
-
allow(SpudUser).to receive(:
|
39
|
+
allow(SpudUser).to receive(:find_by).and_return(user)
|
40
40
|
expect do
|
41
41
|
post :create, params: { email: user.email }
|
42
42
|
end.to have_enqueued_job.on_queue('mailers')
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'should redirect to the login form' do
|
46
|
-
allow(SpudUser).to receive(:
|
46
|
+
allow(SpudUser).to receive(:find_by).and_return(user)
|
47
47
|
|
48
48
|
post :create, params: { email: user.email }
|
49
49
|
expect(response).to redirect_to(admin_login_path)
|
@@ -52,7 +52,7 @@ describe Admin::PasswordResetsController, type: :controller do
|
|
52
52
|
|
53
53
|
context 'with an invalid user email address submitted' do
|
54
54
|
before(:each) do
|
55
|
-
allow(SpudUser).to receive(:
|
55
|
+
allow(SpudUser).to receive(:find_by).and_return(nil)
|
56
56
|
end
|
57
57
|
it 'should re-render the password reset form' do
|
58
58
|
post :create, params: { email: 'invalid@email.com' }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tb_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Woods
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,34 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: jquery-rails
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: jquery-ui-rails
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
75
|
+
version: '6.0'
|
90
76
|
type: :runtime
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - ">="
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
82
|
+
version: '6.0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: breadcrumbs_on_rails
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,6 +294,7 @@ files:
|
|
308
294
|
- app/assets/libs/datepicker/css/datepicker.css
|
309
295
|
- app/assets/libs/datepicker/js/bootstrap-datepicker.js
|
310
296
|
- app/assets/libs/datepicker/less/datepicker.less
|
297
|
+
- app/assets/libs/rails-ujs.js
|
311
298
|
- app/assets/stylesheets/admin/application.css
|
312
299
|
- app/assets/stylesheets/admin/core/application.scss
|
313
300
|
- app/assets/stylesheets/admin/core/jquery_ui.scss
|