forked from nervetattoo/jquery-autosave
-
Notifications
You must be signed in to change notification settings - Fork 1
/
jquery.autosave.js
178 lines (172 loc) · 6.29 KB
/
jquery.autosave.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* jQuery Plugin Autosave
*
* @author Raymond Julin (raymond[dot]julin[at]gmail[dot]com)
* @author Mads Erik Forberg (mads[at]hardware[dot]no)
* @author Simen Graaten (simen[at]hardware[dot]no)
*
* Licensed under the MIT License
*
* Usage:
* $("input.autosave").autosave({
* url: url, // Defaults to parent form url or window.location.href
* method: "post", // Defaults to parent form url or get
* grouped: true, // Defaults to false. States whether all selected fields should be sent in the request or only the one it was triggered upon
* success: function(data) {
* console.log(data);
* },
* send: function(eventTriggeredByNode) {
* // Do stuff while we wait for the ajax response, defaults to doing nothing
* console.log("Saving");
* },
* error: function(xmlReq, text, errorThrown) {
* // Handler if the ajax request fails, defaults to console.log-ing the ajax request scope
* console.log(text);
* },
* dataType: "json" // Defaults to JSON, but can be XML, HTML and so on
* });
*
* $("form#myForm").autosave(); // Submits entire form each time one of the
* // elements are changed, except buttons and submits
*
*
* Todo:
* - Support timed autosave for textareas
*/
(function($) {
$.fn.autosave = function(options) {
/**
* Define some needed variables
* elems is a shortcut for the selected nodes
* nodes is another shortcut for elems later (wtf)
* eventName will be used to set what event to connect to
*/
var elems = $(this), nodes = $(this), eventName;
options = $.extend({
grouped: false,
send: false, // Callback
error: false, // Callback
success: false, // Callback
dataType: "json" // From ajax return point
}, options);
/**
* If the root form is used as selector
* bind to its submit and find all its
* input fields and bind to them
*/
if ($(this).is('form')) {
/* Group all inputelements in this form */
options.grouped = true;
elems = nodes = $(this).find(":input,button");
// Bind to forms submit
// $(this).bind('submit', function(e) {
// e.preventDefault();
// $.fn.autosave._makeRequest(e, nodes, options, $(this));
// });
}
/**
* For each element selected (typically a list of form elements
* that may, or may not, reside in the same form
* Build a list of these nodes and bind them to some
* onchange/onblur events for submitting
*/
elems.each(function(i) {
eventName = 'change'; // $(this).is('button,:submit') ? 'click' : 'change';
$(this).bind(eventName, function (e) {
eventName == 'click' ? e.preventDefault() : false;
$.fn.autosave._makeRequest(e, nodes, options, this);
});
});
return $(this);
}
/**
* Actually make the http request
* using previously supplied data
*/
$.fn.autosave._makeRequest = function(e, nodes, options, actsOn) {
// Keep variables from global scope
var vals = {}, form;
/**
* Further set default options that require
* to actually inspect what node autosave was triggered upon
* Defaults:
* -method: post
* -url: Will default to parent form if one is found,
* if not it will use the current location
*/
form = $(actsOn).is('form') ? $(actsOn) : $(actsOn.form);
options = $.extend({
url: (form.attr('action'))? form.attr('action') : window.location.href,
method: (form.attr('method')) ? form.attr('method') : "post"
}, options);
/**
* If options.grouped is true we collect every
* value from every node
* But if its false we should only push
* the one element we are acting on
*/
if (options.grouped) {
nodes.each(function (i) {
/**
* Do not include button and input:submit as nodes to
* send, EXCEPT if the button/submit was the explicit
* target, aka it was clicked
*/
if (!$(this).is('button,:submit') || e.currentTarget == this) {
if ($(this).is(':radio') && $(this).attr('checked')==false)
return;
if(this.name == "id"){
// alert("id=" + $(this).val());
}
vals[this.name] = $(this).is(':checkbox') ?
$(this).attr('checked') :
$(this).val();
}
});
}
else {
vals[actsOn.name] = $(actsOn).is(':checkbox') ?
$(actsOn).attr('checked') :
$(actsOn).val();
}
console.log(vals);
/**
* Perform http request and trigger callbacks respectively
*/
// Callback triggered when ajax sending starts
options.send ? options.send($(actsOn)) : false;
$.ajax({
type: options.method,
data: vals,
url: options.url,
dataType: options.dataType,
success: function(resp) {
options.success ? options.success(resp) : false;
},
error: function(resp) {
options.error ? options.error(resp) : false;
}
});
}
})(jQuery);
/**
* A default (example) of a visualizer you can use that will
* put a neat loading image in the nearest <legend>
* for the element/form you were autosaving.
* Notice: No default "remover" of this spinner exists
*/
defaultAutosaveSendVisualizer = function(node) {
var refNode;
if (node.is('form'))
refNode = $(node).find('legend');
else
refNode = $(node).parent('fieldset').find('legend');
// Create spinner
var spinner = $('<img src="spin.gif" />').css({
'position':'relative',
'margin-left':'10px',
'height': refNode.height(),
'width': refNode.height()
});
spinner.appendTo(refNode);
}