PageSourceSearch

https://www.unionmart.ru/bitrix/components/bitrix/sale.location.selector.steps/templates/.default/script.js

js unionmart.ru collected 2026-10-01 12:39:27 UTC 12,447 bytes, 469 lines download raw bytes

1BX.namespace('BX.Sale.component.location.selector');
2
3if(typeof BX.Sale.component.location.selector.steps == 'undefined' && typeof BX.ui != 'undefined' && typeof BX.ui.widget != 'undefined'){
4
5	BX.Sale.component.location.selector.steps = function(opts, nf){
6
7		this.parentConstruct(BX.Sale.component.location.selector.steps, opts);
8
9		BX.merge(this, {
10			opts: {
11				bindEvents: {
12					'after-select-item': function(value){
13
14						if(typeof this.opts.callback == 'string' && this.opts.callback.length > 0 && this.opts.callback in window)
15							window[this.opts.callback].apply(this, [value, this]);
16					}
17				},
18				disableKeyboardInput: 	false,
19				dontShowNextChoice: 	false,
20				pseudoValues: 			[], // values that can be only displayed as selected, but not actually selected
21				provideLinkBy: 			'id',
22				requestParamsInject:	false
23			},
24			vars: {
25				cache: {nodesByCode: {}}
26			},
27			sys: {
28				code: 'slst'
29			},
30			flags: {
31				skipAfterSelectItemEventOnce: false
32			}
33		});
34		
35		this.handleInitStack(nf, BX.Sale.component.location.selector.steps, opts);
36	};
37	BX.extend(BX.Sale.component.location.selector.steps, BX.ui.chainedSelectors);
38	BX.merge(BX.Sale.component.location.selector.steps.prototype, {
39
40		// member of stack of initializers, must be defined even if does nothing
41		init: function(){
42			this.pushFuncStack('buildUpDOM', BX.Sale.component.location.selector.steps);
43			this.pushFuncStack('bindEvents', BX.Sale.component.location.selector.steps);
44		},
45
46		// add additional controls
47		buildUpDOM: function(){},
48
49		bindEvents: function(){
50
51			var ctx = this,
52				so = this.opts;
53
54			if(so.disableKeyboardInput){ //toggleDropDown
55				this.bindEvent('after-control-placed', function(adapter){
56
57					var control = adapter.getControl();
58
59					BX.unbindAll(control.ctrls.toggle);
60					// spike, bad idea to access fields directly
61					BX.bind(control.ctrls.scope, 'click', function(e){
62						control.toggleDropDown();
63					});
64				});
65			}
66
67			// quick links
68			BX.bindDelegate(this.getControl('quick-locations', true), 'click', {tag: 'a'}, function(){
69				ctx.setValueByLocationId(BX.data(this, 'id'));
70			});
71		},
72
73		////////// PUBLIC: free to use outside
74
75		setValueByLocationId: function(id){
76			BX.Sale.component.location.selector.steps.superclass.setValue.apply(this, [id]);
77		},
78
79		setValueByLocationIds: function(locationsData){
80
81			if(!locationsData.PARENT_ID)
82				return;
83
84			this.flags.skipAfterSelectItemEventOnce = true;
85			this.setValueByLocationId(locationsData.PARENT_ID);
86
87			this.bindEvent('after-control-placed', function(adapter){
88
89				var control = adapter.getControl();
90
91				if(control.vars.value != false)
92					return;
93
94				if(locationsData.IDS)
95					this.opts.requestParamsInject = {'filter': {'=ID': locationsData.IDS}};
96
97				control.tryDisplayPage('toggle');
98			});
99		},
100
101		setValueByLocationCode: function(code){
102			var sv = this.vars;
103
104			// clean
105			if(code == null || code == false || typeof code == 'undefined' || code.toString().length == 0){ // deselect
106				this.displayRoute([]);
107				this.setValueVariable('');
108				this.setTargetValue('');
109				this.fireEvent('after-clear-selection');
110				return;
111			}
112
113			// set
114			this.fireEvent('before-set-value', [code]);
115
116			var d = new BX.deferred();
117			var ctx = this;
118
119			d.done(BX.proxy(function(route){
120
121				this.displayRoute(route);
122
123				var value = sv.cache.nodesByCode[code].VALUE;
124				sv.value = value;
125				this.setTargetValue(this.checkCanSelectItem(value) ? value : this.getLastValidValue());
126
127			}, this));
128
129			d.fail(function(type){
130				if(type == 'notfound'){
131					
132					ctx.displayRoute([]);
133					ctx.setValueVariable('');
134					ctx.setTargetValue('');
135					ctx.showError({errors: [ctx.opts.messages.nothingFound], type: 'server-logic', options: {}});
136				}
137			});
138
139			this.hideError();
140
141			this.getRouteToNodeByCode(code, d);
142		},
143
144		setValue: function(value){
145			if(this.opts.provideLinkBy == 'id')
146				BX.Sale.component.location.selector.steps.superclass.setValue.apply(this, [value]);
147			else
148				this.setValueByLocationCode(value);
149		},
150
151		setTargetValue: function(value){
152			this.setTargetInputValue(this.opts.provideLinkBy == 'code' ? (value ? this.vars.cache.nodes[value].CODE : ''): value);
153
154			if(!this.flags.skipAfterSelectItemEventOnce)
155				this.fireEvent('after-select-item', [value]);
156			else
157				this.flags.skipAfterSelectItemEventOnce = false;
158		},
159
160		getValue: function(){
161
162			if(this.opts.provideLinkBy == 'id')
163				return this.vars.value === false ? '' : this.vars.value;
164			else{
165				return this.vars.value ? this.vars.cache.nodes[this.vars.value].CODE : '';
166			}
167		},
168
169		getNodeByLocationId: function(value){
170			return this.vars.cache.nodes[value];
171		},
172
173		getSelectedPath: function(){
174
175			var sv = this.vars,
176				result = [];
177
178			if(typeof sv.value == 'undefined' || sv.value == false || sv.value == '')
179				return result;
180
181			if(typeof sv.cache.nodes[sv.value] != 'undefined'){
182
183				var node = sv.cache.nodes[sv.value];
184				while(typeof node != 'undefined')
185				{
186					var item = BX.clone(node);
187					var parentId = item.PARENT_VALUE;
188
189					delete(item.PATH);
190					delete(item.PARENT_VALUE);
191					delete(item.IS_PARENT);
192
193					if(typeof item.TYPE_ID != 'undefined' && typeof this.opts.types != 'undefined')
194						item.TYPE = this.opts.types[item.TYPE_ID].CODE;
195
196					result.push(item);
197
198					if(typeof parentId == 'undefined' || typeof sv.cache.nodes[parentId] == 'undefined')
199						break;
200					else
201						node = sv.cache.nodes[parentId];
202				}
203			}
204
205			return result;
206		},
207
208		////////// PRIVATE: forbidden to use outside (for compatibility reasons)
209
210		setInitialValue: function(){
211
212			if(this.opts.selectedItem !== false) // there will be always a value as ID, no matter what this.opts.provideLinkBy is equal to
213				this.setValueByLocationId(this.opts.selectedItem);
214			else if(this.ctrls.inputs.origin.value.length > 0) // there colud be eiter ID or CODE
215			{
216				if(this.opts.provideLinkBy == 'id')
217					this.setValueByLocationId(this.ctrls.inputs.origin.value);
218				else
219					this.setValueByLocationCode(this.ctrls.inputs.origin.value);
220			}
221		},
222
223		// get route for nodeId and resolve deferred with it
224		getRouteToNodeByCode: function(code, d){
225			var sv = this.vars,
226				ctx = this;
227
228			if(typeof code != 'undefined' && code !== false && code.toString().length > 0){
229
230				var route = [];
231
232				if(typeof sv.cache.nodesByCode[code] != 'undefined')
233					route = this.getRouteToNodeFromCache(sv.cache.nodesByCode[code].VALUE);
234
235				if(route.length == 0){ // || (sv.cache.nodes[nodeId].IS_PARENT && typeof sv.cache.links[nodeId] == 'undefined')){
236
237					// no way existed or item is parent without children downloaded
238
239					// download route, then try again
240					ctx.downloadBundle({
241						request: {CODE: code}, // get only route
242						callbacks: {
243							onLoad: function(data){
244
245								// mark absent as incomplete, kz we do not know if there are really more items of that level or not
246								for(var k in data){
247									if(typeof sv.cache.links[k] == 'undefined')
248										sv.cache.incomplete[k] = true;
249								}
250
251								ctx.fillCache(data, true);
252
253								route = [];
254
255								// trying to re-get
256								if(typeof sv.cache.nodesByCode[code] != 'undefined')
257									route = this.getRouteToNodeFromCache(sv.cache.nodesByCode[code].VALUE);
258
259								if(route.length == 0)
260									d.reject('notfound');
261								else
262									d.resolve(route);
263							},
264							onError: function(){
265								d.reject('internal');
266							}
267						},
268						options: {} // accessible in refineRequest\refineResponce and showError
269					});
270
271				}else
272					d.resolve(route);
273			}else
274				d.resolve([]);
275		},
276
277		addItem2Cache: function(item){
278			this.vars.cache.nodes[item.VALUE] = item;
279			this.vars.cache.nodesByCode[item.CODE] = item;
280		},
281
282		controlChangeActions: function(stackIndex, value){
283
284			var ctx = this,
285				so = this.opts,
286				sv = this.vars,
287				sc = this.ctrls;
288
289			this.hideError();
290
291			////////////////
292
293			if(value.length == 0){
294
295				ctx.truncateStack(stackIndex);
296				sv.value = ctx.getLastValidValue();
297				ctx.setTargetValue(sv.value);
298
299				this.fireEvent('after-select-real-value');
300
301			}else if(BX.util.in_array(value, so.pseudoValues)){
302
303				ctx.truncateStack(stackIndex);
304				ctx.setTargetValue(ctx.getLastValidValue());
305				this.fireEvent('after-select-item', [value]);
306
307				this.fireEvent('after-select-pseudo-value');
308
309			}else{
310
311				var node = sv.cache.nodes[value];
312
313				if(typeof node == 'undefined')
314					throw new Error('Selected node not found in the cache');
315
316				// node found
317
318				ctx.truncateStack(stackIndex);
319
320				if(so.dontShowNextChoice){
321					if(node.IS_UNCHOOSABLE)
322						ctx.appendControl(value);
323				}else{
324					if(typeof sv.cache.links[value] != 'undefined' || node.IS_PARENT)
325						ctx.appendControl(value);
326				}
327
328				if(ctx.checkCanSelectItem(value)){
329					sv.value = value;
330					ctx.setTargetValue(value);
331					this.fireEvent('after-select-real-value');
332				}
333			}
334		},
335
336		// adapter to ajax page request
337		refineRequest: function(request){
338
339			var filter = {};
340			var select = {
341				'VALUE': 'ID',
342				'DISPLAY': 'NAME.NAME',
343				'1': 'TYPE_ID',
344				'2': 'CODE'
345			};
346			var additionals = {};
347
348			if(typeof request['PARENT_VALUE'] != 'undefined'){ // bundle request
349				filter['=PARENT_ID'] = request.PARENT_VALUE;
350				select['10'] = 'IS_PARENT';
351			}
352
353			if(typeof request['VALUE'] != 'undefined'){ // search by id
354				filter['=ID'] = request.VALUE;
355				additionals['1'] = 'PATH';
356			}
357
358			if(BX.type.isNotEmptyString(request['CODE'])){ // search by code
359				filter['=CODE'] = request.CODE;
360				additionals['1'] = 'PATH';
361			}
362
363			if(BX.type.isNotEmptyString(this.opts.query.BEHAVIOUR.LANGUAGE_ID))
364				filter['=NAME.LANGUAGE_ID'] = this.opts.query.BEHAVIOUR.LANGUAGE_ID;
365
366			// we are already inside linked sub-tree, no deeper check for SITE_ID needed
367			if(BX.type.isNotEmptyString(this.opts.query.FILTER.SITE_ID)){
368
369				if(typeof this.vars.cache.nodes[request.PARENT_VALUE] == 'undefined' || this.vars.cache.nodes[request.PARENT_VALUE].IS_UNCHOOSABLE)
370					filter['=SITE_ID'] = this.opts.query.FILTER.SITE_ID;
371			}
372
373			var result =  {
374				'select': select,
375				'filter': filter,
376				'additionals': additionals,
377				'version': '2'
378			};
379
380			if(this.opts.requestParamsInject)
381			{
382				for(var type in this.opts.requestParamsInject)
383				{
384					if(this.opts.requestParamsInject.hasOwnProperty(type))
385					{
386						if(result[type] == undefined)
387							result[type] = {};
388
389						for(var param in this.opts.requestParamsInject[type])
390						{
391							if(this.opts.requestParamsInject[type].hasOwnProperty(param))
392							{
393								if(result[type][param] != undefined)
394								{
395									var tmp = result[type][param];
396									result[type][param] = [];
397									result[type][param].push(tmp);
398								}
399								else
400								{
401									result[type][param] = [];
402								}
403
404								for(var val in this.opts.requestParamsInject[type][param])
405									if(this.opts.requestParamsInject[type][param].hasOwnProperty(val))
406										result[type][param].push(this.opts.requestParamsInject[type][param][val]);
407							}
408						}
409					}
410				}
411			}
412
413			return result;
414		},
415
416		// adapter to ajax page responce
417		refineResponce: function(responce, request){
418
419			if(responce.length == 0)
420				return responce;
421
422			if(typeof request.PARENT_VALUE != 'undefined'){ // it was a bundle request
423
424				var r = {};
425				r[request.PARENT_VALUE] = responce['ITEMS'];
426				responce = r;
427
428			}else if(typeof request.VALUE != 'undefined' || typeof request.CODE != 'undefined'){ // it was a route request
429
430				var levels = {};
431
432				if(typeof responce.ITEMS[0] != 'undefined' && typeof responce.ETC.PATH_ITEMS != 'undefined'){
433
434					var parentId = 0;
435
436					for(var k = responce.ITEMS[0]['PATH'].length - 1; k >= 0; k--){
437
438						var itemId = responce.ITEMS[0]['PATH'][k];
439						var item = responce.ETC.PATH_ITEMS[itemId];
440
441						item.IS_PARENT = true;
442
443						levels[parentId] = [item];
444
445						parentId = item.VALUE;
446					}
447
448					// add item itself
449					levels[parentId] = [responce.ITEMS[0]];
450				}
451
452				responce = levels;
453			}
454
455			return responce;
456		},
457
458		showError: function(parameters){
459
460			if(parameters.type != 'server-logic')
461				parameters.errors = [this.opts.messages.error]; // generic error on js error
462
463			this.ctrls.errorMessage.innerHTML = '<p><font class="errortext">'+BX.util.htmlspecialchars(parameters.errors.join(', '))+'</font></p>';
464			BX.show(this.ctrls.errorMessage);
465
466			BX.debug(parameters);
467		}
468	});
469}

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.