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.