PageSourceSearch

https://voenchast.ru/bitrix/js/main/core/core_autosave.js

js voenchast.ru collected 2026-10-09 22:40:12 UTC 9,742 bytes, 440 lines download raw bytes

1(function(window){
2	var topWindow = BX.PageObject.getRootWindow();
3if (BX.CAutoSave && topWindow.BX.CAutoSave) return;
4/******************************* AUTOSAVE *********************************/
5
6BX.CAutoSave = function(params)
7{
8	this.FORM_NAME = params.form;
9	this.FORM_MARKER = params.form_marker;
10	this.FORM_ID = params.form_id;
11
12	this.PERIOD = params.period || [4001, 20990];
13
14	this.RESTORE_DATA = null;
15	this.TIMERS = [null, null];
16
17	this.bInited = false;
18	this.bRestoreInProgress = false;
19
20	this.DISABLE_STANDARD_NOTIFY = params.DISABLE_STANDARD_NOTIFY;
21	this.NOTIFY_CONTEXT = null;
22
23	BX.ready(BX.defer(this.Prepare, this));
24	BX.garbage(BX.delegate(this.Clear, this));
25
26	if (
27		BX.type.isNotEmptyString(this.FORM_MARKER)
28		&& BX(this.FORM_MARKER)
29	)
30	{
31		var formMarker = BX(this.FORM_MARKER);
32		if (
33			BX(formMarker.form)
34			&& BX.type.isNotEmptyString(formMarker.form.name)
35		)
36		{
37			BX.addCustomEvent(topWindow, 'onExtAutoSaveReset_' + formMarker.form.name, BX.proxy(this.Reset, this));
38		}
39	}
40};
41
42BX.CAutoSave.prototype.Prepare = function()
43{
44	var i;
45
46	if (this.FORM_NAME && BX.type.isString(this.FORM_NAME))
47		this.FORM = document.forms[this.FORM_NAME];
48	else if (this.FORM_MARKER && BX.type.isString(this.FORM_MARKER))
49		this.FORM = (BX(this.FORM_MARKER)||{form:null}).form;
50
51	if (!BX.type.isDomNode(this.FORM))
52		return;
53
54	this.FORM.BXAUTOSAVE = this;
55	BX.bind(this.FORM, 'submit', BX.proxy(this.ClearTimers, this));
56
57	for (i=0; i<this.FORM.elements.length; i++)
58	{
59		this.RegisterInput(this.FORM.elements[i]);
60	}
61
62	setTimeout(BX.delegate(this._PrepareAfter, this), 10);
63};
64
65BX.CAutoSave.prototype.RegisterInput = function(inp)
66{
67	if (BX.type.isString(inp))
68	{
69		setTimeout(BX.delegate(function(){this.RegisterInput(this.FORM[inp] || BX(inp))}, this), 10);
70	}
71	else if (BX.type.isDomNode(inp))
72	{
73		if (
74			inp.type != 'button'
75			&& inp.type != 'submit'
76			&& inp.type != 'reset'
77			&& inp.type != 'image'
78			&& inp.type != 'hidden'
79		)
80		{
81			BX.bind(inp, 'change', BX.proxy(this.Init, this));
82
83			if (inp.type == 'text' || inp.type == 'textarea')
84			{
85				BX.bind(inp, 'keyup', BX.proxy(this.Init, this));
86			}
87
88			if (inp.type == 'checkbox' || inp.type == 'radio')
89			{
90				BX.bind(inp, 'click', BX.proxy(this.Init, this));
91			}
92		}
93	}
94};
95
96BX.CAutoSave.prototype.UnRegisterInput = function(inp)
97{
98	if (BX.type.isString(inp))
99		inp = this.FORM[inp] || BX(inp);
100	if (BX.type.isDomNode(inp))
101	{
102		BX.unbind(inp, 'change', BX.proxy(this.Init, this));
103		BX.unbind(inp, 'keyup', BX.proxy(this.Init, this));
104		BX.unbind(inp, 'click', BX.proxy(this.Init, this));
105	}
106};
107
108BX.CAutoSave.prototype._PrepareAfter = function()
109{
110	// we can set other "target events" here
111	BX.onCustomEvent(this.FORM, 'onAutoSavePrepare', [this, BX.proxy(this.Init, this)]);
112
113	if (this.RESTORE_DATA)
114	{
115		var id = this.FORM.name || Math.random();
116		BX.removeCustomEvent('onExtAutoSaveRestoreClick_' + id, BX.proxy(this.Restore, this));
117		BX.addCustomEvent('onExtAutoSaveRestoreClick_' + id, BX.proxy(this.Restore, this));
118
119		var o = this._NotifyContext();
120		if (o)
121		{
122			o.Notify(
123				BX.message('AUTOSAVE') + ' <a href="javascript:void(0)" onclick="BX.CAutoSave.Re
123store(\'' + BX.util.urlencode(id) + '\', this); return false;">' +	BX.message('AUTOSAVE_R') + '</a>',
124				false,
125				true
126			);
127		}
128
129		// may be useful sometimes
130		BX.onCustomEvent(this.FORM, 'onAutoSaveRestoreFound', [this, this.RESTORE_DATA]);
131	}
132};
133
134BX.CAutoSave.prototype.Init = function()
135{
136	// if (this.bRestoreInProgress)
137		// return;
138
139	if (this.TIMERS[0])
140	{
141		clearTimeout(this.TIMERS[0]);
142		this.TIMERS[0] = null;
143	}
144
145	this.TIMERS[0] = setTimeout(BX.proxy(this.TimerHandler, this), this.PERIOD[0]);
146
147	if (!this.TIMERS[1])
148	{
149		this.TIMERS[1] = setInterval(BX.proxy(this.Save, this), this.PERIOD[1]);
150	}
151
152	// may also be useful
153	BX.onCustomEvent(this.FORM, 'onAutoSaveInit', [this]);
154
155	return true;
156};
157
158BX.CAutoSave.prototype.TimerHandler = function()
159{
160	if (this.TIMERS[1])
161	{
162		clearInterval(this.TIMERS[1]);
163		this.TIMERS[1] = null;
164	}
165	this.Save();
166};
167
168BX.CAutoSave.prototype.Save = function()
169{
170	if (this.FORM && BX.isNodeInDom(this.FORM))
171	{
172		var i, j, el, data = {autosave_id: this.FORM_ID, form_data: {}};
173
174		for (i=0; i<this.FORM.elements.length; i++)
175		{
176			el = this.FORM.elements[i];
177
178			if (el.name && el.name != 'sessid' && el.name != 'lang' && el.name != 'autosave_id')
179			{
180				var n = el.name, v = '', t = el.type.toLowerCase();
181
182				switch (t)
183				{
184					case 'button':
185					case 'submit':
186					case 'reset':
187					case 'image':
188					case 'file':
189					case 'password':
190						break;
191
192					case 'radio':
193					case 'checkbox':
194						if (el.checked)
195							v = el.value || 'on';
196					break;
197
198					case 'select-multiple':
199						n = n.substring(0, n.length-2);
200						v = [];
201						for (j=0;j<el.options.length;j++)
202						{
203							if (el.options[j].selected)
204							{
205								v.push(el.options[j].value);
206							}
207						}
208					break;
209
210					default:
211						v = el.value;
212				}
213
214				if (n.indexOf('[]') > 0)
215				{
216					n = _encodeName(n);
217					if (typeof(data.form_data[n]) == 'undefined')
218						data.form_data[n] = [v];
219					else
220						data.form_data[n].push(v);
221				}
222				else
223					data.form_data[_encodeName(n)] = v;
224			}
225		}
226
227		// we can adjust form_data before autosaving
228		BX.onCustomEvent(this.FORM, 'onAutoSave', [this, data.form_data]);
229		BX.ajax.post(
230			'/bitrix/tools/autosave.php?bxsender=core_autosave&sessid=' + BX.bitrix_sessid(), data, BX.proxy(this._Save, this)
231		);
232	}
233	else
234	{
235		this.Clear();
236	}
237};
238
239BX.CAutoSave.prototype.Reset = function()
240{
241	if (this.FORM && BX.isNodeInDom(this.FORM))
242	{
243		BX.ajax.post(
244			'/bitrix/tools/autosave.php?bxsender=core_autosave&action=reset&sessid=' + BX.bitrix_sessid(), {autosave_id: this.FORM_ID }, null
245		);
246	}
247};
248
249BX.CAutoSave.prototype._Save = function(data)
250{
251	BX.onCustomEvent(this.FORM, 'onAutoSaveFinished', [this, data]);
252};
253
254BX.CAutoSave.prototype.Restore = function(data, clicker)
255{
256	if (data)
257	{
258		this.RESTORE_DATA = _decodeData(data);
259	}
260	else if (this.FORM && this.RESTORE_DATA)
261	{
262		// we can change restore data or make some unusual actions here
263		BX.onCustomEvent(this.FORM, 'onAutoSaveRestore', [this, this.RESTORE_DATA]);
264
265		this.bRestoreInProgress = true;
266
267		for (var i=0; i<this.FORM.elements.length; i++)
268		{
269			var el = this.FORM.elements[i];
270			if (el && BX.type.isDomNode(el) && el.name)
271			{
272				var value = undefined, n = el.name;
273
274				if (el.type == 'select-multiple')
275					n = el.name.substring(0, el.name.length-2);
276
277				value = this.RESTORE_DATA[n];
278
279				if (n.indexOf('[]') > 0 && BX.type.isArray(value))
280					value = this.RESTORE_DATA[n].shift();
281
282				if (el.type != 'checkbox' && typeof value == 'undefined')
283					continue;
284
285				var bChange = false;
286
287				switch(el.type)
288				{
289					case 'radio':
290						if (!el.checked && !!(value == el.value))
291						{
292							bChange = true;
293							BX.fireEvent(el, 'click');
294						}
295					break;
296					case 'checkbox':
297						if (el.checked != !!(value == el.value))
298						{
299							bChange = true;
300							BX.fireEvent(el, 'click');
301						}
302					break;
303
304					case 'select-one':
305						for (var j = 0; j < el.options.length; j++)
306						{
307							var q = el.options[j].selected;
308							el.options[j].selected = !!(value == el.options[j].value);
309							bChange |= el.options[j].selected != q;
310						}
311
312						break;
313
314					case 'select-multiple':
315						value = this.RESTORE_DATA[el.name.substring(0, el.name.length-2)];
316						for (j = 0; j < el.options.length; j++)
317						{
318							q = el.options[j].selected;
319							el.options[j].selected = !!(BX.type.isArray(value) && BX.util.in_array(el.options[j].value, value));
320							bChange |= el.options[j].selected != q;
321						}
322						break;
323
324					case 'file':
325					case 'button':
326					case 'image':
327					case 'submit':
328					case 'reset':
329					case 'password':
330						break;
331
332					default:
333						bChange = value != el.value;
334						el.value = value;
335				}
336
337				if (bChange)
338					BX.fireEvent(el, 'change');
339			}
340		}
341
342		var o = this._NotifyContext();
343		if (o)
344			o.hideNotify(clicker.parentNode.parentNode);
345
346		this.bRestoreInProgress = false;
347
348		BX.onCustomEvent(this.FORM, 'onAutoSaveRestoreFinished', [this, this.RESTORE_DATA]);
349	}
350};
351
352BX.CAutoSave.prototype._NotifyContext = function()
353{
354	var o = null;
355
356	if (!this.DISABLE_STANDARD_NOTIFY)
357	{
358		if (this.NOTIFY_CONTEXT)
359			o = this.NOTIFY_CONTEXT;
360		else if (BX.WindowManager && BX.WindowManager.Get())
361			o = BX.WindowManager.Get();
362		else if (BX.adminPanel)
363			o = BX.adminPanel;
364		else if (BX.admin && BX.admin.panel)
365			o = BX.admin.panel;
366
367		this.NOTIFY_CONTEXT = o;
368	}
369
370	return o;
371};
372
373BX.CAutoSave.prototype.ClearTimers = function()
374{
375	if (this.TIMERS)
376	{
377		clearTimeout(this.TIMERS[0]);
378		clearInterval(this.TIMERS[1]);
379	}
380};
381
382BX.CAutoSave.prototype.Clear = function()
383{
384	if (this.FORM)
385	{
386		this.FORM.BXAUTOSAVE = null;
387
388		for (var i=0; i<this.FORM.elements.length; i++)
389		{
390			this.UnRegisterInput(this.FORM.elements[i]);
391		}
392	}
393
394	this.ClearTimers();
395
396	// we should unset any additional "target events" here
397	BX.onCustomEvent(this.FORM, 'onAutoSaveClear', [this]);
398
399	this.FORM = null;
400	this.TIMERS = null;
401};
402
403BX.CAutoSave.Restore = function(id, el)
404{
405	BX.onCustomEvent('onExtAutoSaveRestoreClick_' + id, [null, el]);
406};
407
408function _encodeName(n)
409{
410	var q;
411	while (q = /[^a-zA-Z0-9_\-]/.exec(n))
412	{
413		n = n.replace(q[0], 'X' + BX.util.str_pad_left(q[0].charCodeAt(0).toString(), 6, '0') + 'X');
414	}
415	return n;
416}
417
418function _decodeName(n)
419{
420	var q;
421	while (q = /X[\d]{6}X/.exec(n))
422	{
423		n = n.replace(q[0], String.fromCharCode(parseInt(q[0].replace(/(^X[0]*)|(X$)/g, ''))))
424	}
425	return n;
426}
427
428function _decodeData(data)
429{
430	var d = {};
431	for (var i in data)
432	{
433		d[_decodeName(i)] = data[i];
434	}
435	return d;
436}
437	topWindow.BX.CAutoSave = BX.CAutoSave;
438})(window);
439
440

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.