1function CartDataAccessor() { 2 this.LoadItems = function (loadHandler) { 3 $.get("/api/basket/get/", function (data) { 4 if (loadHandler) { 5 loadHandler(data); 6 } 7 }) 8 .fail(function () { 9 loadHandler(null); 10 }); 11 } 12 13 this.UpdateBasket = function (items, loadHandler) { 14 $.post("/api/basket/change/", JSON.stringify({change: items}), function (data) { 15 if (loadHandler) { 16 loadHandler(data); 17 } 18 19 let open = $('.cart-block').hasClass('active') ? 1 : 0; 20 let url = "/ajax/topbasket.php"; 21 22 $.post(url, {"BASKET_OPEN": open}, function(data) { 23 $(".cart-wrapper").html(data); 24 }); 25 }) 26 .fail(function () { 27 loadHandler(null); 28 }); 29 } 30 31 this.DeletePositions = function (positionIds, loadHandler) { 32 $.post("/api/basket/delete/", JSON.stringify({delete: positionIds}), function (data) { 33 if (loadHandler) { 34 loadHandler(data); 35 } 36 }) 37 .fail(function () { 38 loadHandler(null); 39 }); 40 } 41 42 this.GetRecommendedProducts = function (loadHandler) { 43 $.get("/api/basket/get-recommended/", function (data) { 44 if (loadHandler) { 45 loadHandler(data); 46 } 47 }) 48 .fail(function () { 49 loadHandler(null); 50 }); 51 } 52} 53 54function CartManager(totalOuterSelector, cartContainerSelector, cartProductsCountSelector, dataAccessorHelper) { 55 let _this = this; 56 this._dataAccessorHelper = dataAccessorHelper; 57 this._saveItemsTimeout = 1000; 58 this._cartContainerSelector = cartContainerSelector; 59 this._cartProductsCountSelector = cartProductsCountSelector; 60 this._dataAccessor = new CartDataAccessor(); 61 62 this.Init = function () { 63 _this._container = $(_this._cartContainerSelector); 64 _this._cartProductsCount = $(_this._cartProductsCountSelector); 65 _this._dataAccessor.LoadItems(_this.UploadItems); 66 } 67 68 this._timeoutID = null; 69 70 this._cartChanged = function () { 71 _this._spinner.Display(); 72 _this.LockButtons(); 73 if (_this.timeoutID !== null) { 74 clearTimeout(_this.timeoutID); 75 } 76 this.timeoutID = setTimeout( 77 _this.SaveNewCartParameters, 78 _this._saveItemsTimeout); 79 } 80 81 this.SaveNewCartParameters = function () { 82 let toUpdate = []; 83 for (let id in _this._itemsInfo) { 84 toUpdate.push({ 85 id: id, 86 quantity: _this._itemsInfo[id].quantity, 87 checked: _this._itemsInfo[id].checked 88 }); 89 } 90 _this._dataAccessor.UpdateBasket(toUpdate, _this.UploadItems); 91 } 92 93 this.UploadItems = function (response) { 94 response = _this._dataAccessorHelper.ProcessApiResponse(response); 95 96 if(response != null) { 97 _this._itemsInfo = {}; 98 let allChecked = true; 99 let allUnchecked = true; 100 if (_this.WasLoadedAnyItems(response)) { 101 for (let i = 0; i < response.basket.items.length; i++) { 102 const item = response.basket.items[i]; 103 const isChecked = item.checked === false ? false : true; 104 _this._itemsInfo[item.id] = { 105 quantity: item.quantity > item.maxquantity ? item.maxquantity : item.quantity, 106 checked: isChecked 107 } 108 if (!isChecked) { 109 allChecked = false; 110 } 111 if (isChecked) { 112 allUnchecked = false; 113 } 114 } 115 } 116 _this._allChecked = allChecked === true ? true : (allUnchecked === true ? false : null); 117 _this.RenderItems(response); 118 } 119 } 120 121 this.RenderItems = function (response) { 122 if(response != null) { 123 if (!_this.WasLoadedAnyItems(response)) { 124 _this._container.html("<div class=\"cart-empty\">РкоÑзине Ð½ÐµÑ ÑоваÑов</div>"); 125 } else { 126 let html = "<div class=\"order-body\">"; 127 128 html += "<div class=\"order-content\">"; 129 html += "<div class=\"cart-header\">"; 130 html += "<div class=\"cart-header-checkbox\"><input type=\"checkbox\" class=\"select-all\" /> ÐÑбÑаÑÑ</div><div class=\"cart-header-delete\"><button class=\"delete-selected\">УдалиÑÑ Ð²ÑбÑанное</button></div>"; 131 html += "</div>"; 132 html += "<hr />"; 133 134 for (let i = 0; i < response.basket.items.length; i++) { 135 let item = response.basket.items[i]; 136 137 html += "<div class=\"product-item\">"; 138 html += "<div class=\"product-item-image-description-column\">"; 139 html += "<div class=\"product-item-checkbox-column\">"; 140 html += "<input productId=\"" + item.id + "\" type=\"checkbox\" class=\"select-item\" " + (_this._itemsInfo[item.id].checked ? "checked" : "") + " />"; 141 html += "</div>"; 142 html += "<div class=\"product-item-image-column\">"; 143 html += "<img src=\"" + item.image + "\" />"; 144 html += "</div>"; 145 html += "<div class=\"product-item-info-column\">"; 146 if (!item.available) { 147 html += "<div class=\"product-item-not-available\">ÐÑеменно Ð½ÐµÑ Ð² налиÑии</div>"; 148 } 149 html += "<div class=\"product-item-article\">
149ÐÑÑикÑл: " + item.article + "</div>"; 150 html += "<div class=\"product-item-name\"><a href=\"" + item.pageUrl + "\" target='_blank'>" + item.name + "</a></div>"; 151 html += "<div class=\"product-item-sku\">" + item.skutext + "</div>"; 152 html += "</div>"; 153 html += "</div>"; 154 155 html += "<div class=\"product-item-count-price-column\">"; 156 157 html += "<div class=\"product-item-count-column\">"; 158 html += "<input productId=\"" + item.id + "\" class=\"item-count-input\" min-value=\"1\" max-value=\"" + item.maxquantity + "\" value=\"" + _this._itemsInfo[item.id].quantity + "\" />"; 159 html += "</div>"; 160 161 if (item.price) { 162 let actualPrice = item.price.discount ? item.price.discount : item.price.base; 163 html += "<div class=\"product-item-actual-price\">" + FormatNumberWithSeparator(actualPrice) + " " + item.price.currency + "</div>"; 164 if (item.price.discount) { 165 html += "<div class=\"product-item-discount\"><span class=\"product-item-discount-amount\">" + FormatNumberWithSeparator(item.price.base) + " " + item.price.currency + "</span>"; 166 if (item.price.percent) { 167 html += "<span class=\"product-item-discount-percent\">-" + item.price.percent + "%</span>"; 168 } 169 html += "</div>"; 170 } 171 } 172 html += "</div>"; 173 174 html += "</div>"; 175 html += "<hr />"; 176 } 177 178 html += "</div>"; 179 180 html += "<div class=\"order-total\">"; 181 html += "<div class=\"total-header\">ÐÐ°Ñ Ð·Ð°ÐºÐ°Ð·</div>"; 182 html += "<div class=\"total-price-count\">"; 183 html += "<div class=\"total-count\">" + GetOrderWordFormByCount(response.basket.itemsCount); 184 html += "</div>"; 185 html += "<div class=\"total-price\">"; 186 187 let actualPrice = response.basket.total.discount ? response.basket.total.discount : response.basket.total.base; 188 if (response.basket.total.discount) { 189 html += "<span class=\"total-discount\">" + FormatNumberWithSeparator(response.basket.total.base) + " " + response.basket.total.currency + "</span>"; 190 } 191 html += "<span class=\"total-actual-price\">" + FormatNumberWithSeparator(actualPrice) + " " + response.basket.total.currency + "</span>"; 192 193 html += "</div>"; 194 html += "</div>"; 195 html += "<hr />"; 196 html += "<div class=\"total-buttons\">"; 197 html += "<button onclick=\"window.location = '/personal/cart/order/'\" class=\"btn btn-primary btn-primary-rectangle send-order\"></button>"; 198 html += "<a class=\"btn btn-primary btn-primary-rectangle btn-primary-white continue-shopping\" href=\"/catalog/\"></a>"; 199 html += "</div>"; 200 html += "</div>"; 201 202 html += "</div>"; 203 _this._container.html(html); 204 _this._cartProductsCount.html("(" + GetOrderWordFormByCount(response.basket.totalCount) + ")"); 205 206 _this.SendOrderButton = _this._container.find('.send-order'); 207 _this.DeleteSelectedButton = _this._container.find('.delete-selected'); 208 209 _this._container.find('.item-count-input').customNumberInput({ 210 onChange: function (ev) { 211 _this._itemsInfo[ev.element.sourceElement.attr("productId")].quantity = ev.value; 212 _this._cartChanged(); 213 } 214 }); 215 _this._selectAllCheckbox = _this._container.find('.select-all').customCheckBox({ 216 onChange: function (ev) { 217 _this.SetChecked(null, ev.value); 218 } 219 })[0]; 220 _this._selectAllCheckbox.SetValue(_this._allChecked); 221 _this._selectItemsCheckboxes = _this._container.find('.select-item').customCheckBox({ 222 onChange: function (ev) { 223 _this.SetChecked([ev.element.sourceElement.attr("productId")], ev.value); 224 } 225 }); 226 _this._container.find('.delete-selected').click(function () { 227 let positionIds = []; 228 for (let id in _this._itemsInfo) { 229 if (_this._itemsInfo[id].checked === true) { 230 positionIds.push(id); 231 } 232 } 233 if (positionIds.length > 0) { 234 _this.LockButtons(); 235 _this._dataAccessor.DeletePositions(positionIds, _this.UploadItems); 236 } 237 }); 238 239 240 _this._spinner = _this._container.find(totalOuterSelector).spinner(); 241 _this._spinner = _this._spinner.length === 1 ? _this._spinner[0] : null; 242 } 243 } 244 } 245 246 this.SetChecked = function (ids, value) { 247 let allChecked = true; 248 let allUnchecked = true; 249 for (let i = 0; i < _this._selectItemsCheckboxes.length; i++) { 250 const e = $(_this._selectItemsCheckboxes[i].sourceElement);
251 const productId = e.attr("productId"); 252 if (ids === null || ids.indexOf(productId) >= 0) { 253 _this._itemsInfo[productId].checked = value; 254 _this._selectItemsCheckboxes[i].SetValue(value); 255 } 256 if (!_this._itemsInfo[productId].checked) { 257 allChecked = false; 258 } 259 if (_this._itemsInfo[productId].checked) { 260 allUnchecked = false; 261 } 262 } 263 264 const allValue = allChecked === true ? true : (allUnchecked === true ? false : null); 265 _this._selectAllCheckbox.SetValue(allValue); 266 _this._cartChanged(); 267 } 268 269 this.WasLoadedAnyItems = function (response) { 270 return response && response.basket && response.basket.items && response.basket.items.length > 0; 271 } 272 273 this.LockButtons = function () { 274 _this.SendOrderButton.prop("disabled", true); 275 _this.DeleteSelectedButton.prop("disabled", true); 276 } 277} 278 279function RecommendedProductsManager(selector, dataAccessorHelper) { 280 let _this = this; 281 this._dataAccessor = new CartDataAccessor(); 282 283 this._dataAccessorHelper = dataAccessorHelper; 284 this._selector = selector; 285 286 this.Init = function () { 287 _this._container = $(_this._selector); 288 _this._dataAccessor.GetRecommendedProducts(_this.RenderItems); 289 } 290 291 this.RenderItems = function (response) { 292 response = _this._dataAccessorHelper.ProcessApiResponse(response); 293 if (response != null && _this.WasLoadedAnyItems(response)) { 294 let html = "<h3 class=\"header\">РекомендÑем</h3>"; 295 html += "<div class=\"recommended-products-outer\">"; 296 html += "<div class=\"recommended-products-inner\">"; 297 for (let i = 0; i < response.length; i++) { 298 const item = response[i]; 299 html += "<div class=\"recommended-product\">"; 300 html += "<div class=\"recommended-product-image\">"; 301 html += "<img src=\"" + item.image + "\">"; 302 html += "</div>"; 303 html += "<div class=\"product-item-article\">ÐÑÑикÑл: " + item.article + "</div>"; 304 html += "<div class=\"product-item-name\"><a href=\"" + item.link + "\">" + item.name + "</a></div>"; 305 html += "<div class=\"product-item-sku\">" + item.skutext + "</div>"; 306 307 if (item.price) { 308 let actualPrice = item.price.discount ? item.price.discount : item.price.base; 309 html += "<div class=\"product-item-actual-price\">" + FormatNumberWithSeparator(actualPrice) + " " + item.price.currency + "</div>"; 310 if (item.price.discount) { 311 html += "<div class=\"product-item-discount\"><span class=\"product-item-discount-amount\">" + FormatNumberWithSeparator(item.price.base) + " " + item.price.currency + "</span>"; 312 if (item.price.percent) { 313 html += "<span class=\"product-item-discount-percent\">-" + item.price.percent + "%</span>"; 314 } 315 html += "</div>"; 316 } 317 } 318 html += "<a href=\"" + item.link + "\" class=\"btn btn-primary btn-primary-rectangle add-to-cart\"></a>"; 319 320 html += "</div>"; 321 } 322 html += "</div>"; 323 html += "</div>"; 324 _this._container.html(html); 325 } 326 } 327 328 this.WasLoadedAnyItems = function (response) { 329 return response && response.length > 0; 330 } 331}
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.