iwgt 2.4.6 → 2.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1037 @@
1
+ {
2
+ "version": "3.0.0",
3
+ "title": "Полный справочник CommonJS API v2 для InSales",
4
+ "description": "Библиотека common.v2.js создана для минимизации JavaScript кода. Большинство функций работают через data-атрибуты БЕЗ написания JS. Все модули доступны глобально через window.",
5
+ "generatedAt": "2025-01-08",
6
+ "critical_info": {
7
+ "no_imports_needed": "⚠️ ВСЕ модули доступны ГЛОБАЛЬНО через window. НЕ НУЖНО использовать import или require!",
8
+ "declarative_first": "✅ ПРИОРИТЕТ: используйте data-атрибуты вместо JavaScript где возможно",
9
+ "lodash_not_global": "⚠️ Lodash НЕ глобальный! Он импортируется внутри модулей CommonJS. В виджетах используйте нативный JS или jQuery.",
10
+ "jquery_is_global": "✅ jQuery доступен глобально как $ и jQuery",
11
+ "minimal_js": "💡 Библиотека создана чтобы писать МИНИМУМ JavaScript - используйте декларативный подход"
12
+ },
13
+ "installation": {
14
+ "method": "liquid_tag",
15
+ "code": "{% include_insales_scripts \"common-js@v2\" %}",
16
+ "description": "Добавьте этот тег в layout.liquid перед закрывающим </body>",
17
+ "note": "После подключения ВСЕ модули доступны глобально"
18
+ },
19
+ "global_modules": {
20
+ "Cart": {
21
+ "description": "Управление корзиной",
22
+ "global_access": "window.Cart или window.InsalesCommonCart",
23
+ "type": "class",
24
+ "declarative": true,
25
+ "declarative_note": "Большинство функций работают через data-атрибуты БЕЗ JavaScript",
26
+ "data_attributes": {
27
+ "data-cart-form": {
28
+ "required": true,
29
+ "description": "Обязательный атрибут для формы корзины",
30
+ "example": "<form data-cart-form>...</form>",
31
+ "note": "Инициализирует корзину автоматически"
32
+ },
33
+ "data-item-id": {
34
+ "description": "ID позиции в корзине",
35
+ "example": "<div data-item-id=\"{{ item.id }}\">...</div>"
36
+ },
37
+ "data-item-delete": {
38
+ "description": "Кнопка удаления позиции",
39
+ "example": "<button data-item-delete>Удалить</button>",
40
+ "no_js_needed": true
41
+ },
42
+ "data-cart-clear": {
43
+ "description": "Очистить всю корзину",
44
+ "example": "<button data-cart-clear>Очистить корзину</button>",
45
+ "no_js_needed": true
46
+ },
47
+ "data-cart-total-price": {
48
+ "description": "Общая сумма корзины",
49
+ "example": "<span data-cart-total-price></span>",
50
+ "auto_updates": true
51
+ },
52
+ "data-cart-full-total-price": {
53
+ "description": "Сумма с учетом скидок",
54
+ "example": "<span data-cart-full-total-price></span>",
55
+ "auto_updates": true
56
+ },
57
+ "data-cart-positions-count": {
58
+ "description": "Количество позиций",
59
+ "example": "<span data-cart-positions-count></span>",
60
+ "auto_updates": true
61
+ },
62
+ "data-cart-item-count": {
63
+ "description": "Количество товаров",
64
+ "example": "<span data-cart-item-count></span>",
65
+ "auto_updates": true
66
+ },
67
+ "data-coupon-submit": {
68
+ "description": "Применить купон",
69
+ "example": "<button data-coupon-submit>Применить</button>",
70
+ "no_js_needed": true
71
+ },
72
+ "data-cart-discounts-ajax": {
73
+ "description": "Вывод скидок через AJAX",
74
+ "example": "<div data-cart-discounts-ajax></div>",
75
+ "auto_updates": true
76
+ },
77
+ "data-item-accessories": {
78
+ "description": "Опции товара в корзине",
79
+ "example": "<div data-item-accessories>...</div>"
80
+ }
81
+ },
82
+ "methods": {
83
+ "add": {
84
+ "description": "Добавить товар в корзину",
85
+ "params": [
86
+ { "name": "variant_id", "type": "number", "required": true },
87
+ { "name": "quantity", "type": "number", "default": 1 },
88
+ { "name": "comment", "type": "string", "optional": true }
89
+ ],
90
+ "returns": "Promise",
91
+ "example": "Cart.add(12345, 2).then(data => console.log(data));",
92
+ "note": "Обычно НЕ нужен - используйте data-item-add"
93
+ },
94
+ "update": {
95
+ "description": "Обновить количество",
96
+ "params": [
97
+ { "name": "order_line_id", "type": "number", "required": true },
98
+ { "name": "quantity", "type": "number", "required": true }
99
+ ],
100
+ "returns": "Promise",
101
+ "example": "Cart.update(123, 3);",
102
+ "note": "Обычно НЕ нужен - работает автоматически"
103
+ },
104
+ "remove": {
105
+ "description": "Удалить позицию",
106
+ "params": [{ "name": "order_line_id", "type": "number", "required": true }],
107
+ "returns": "Promise",
108
+ "example": "Cart.remove(123);",
109
+ "note": "Обычно НЕ нужен - используйте data-item-delete"
110
+ },
111
+ "clear": {
112
+ "description": "Очистить корзину",
113
+ "returns": "Promise",
114
+ "example": "Cart.clear();",
115
+ "note": "Обычно НЕ нужен - используйте data-cart-clear"
116
+ },
117
+ "setCoupon": {
118
+ "description": "Установить купон",
119
+ "params": [{ "name": "coupon", "type": "string", "required": true }],
120
+ "returns": "Promise",
121
+ "example": "Cart.setCoupon('SALE2024');",
122
+ "note": "Обычно НЕ нужен - используйте data-coupon-submit"
123
+ }
124
+ },
125
+ "events": {
126
+ "add_items:insales:cart": {
127
+ "description": "Товар добавлен в корзину",
128
+ "data": "{ order_lines: [...], cart: {...} }",
129
+ "example": "EventBus.subscribe('add_items:insales:cart', data => console.log(data));"
130
+ },
131
+ "update_items:insales:cart": {
132
+ "description": "Корзина обновлена",
133
+ "data": "{ order_lines: [...], cart: {...} }"
134
+ },
135
+ "delete_items:insales:cart": {
136
+ "description": "Товар удален",
137
+ "data": "{ order_lines: [...], cart: {...} }"
138
+ },
139
+ "clear_items:insales:cart": {
140
+ "description": "Корзина очищена",
141
+ "data": "{ cart: {...} }"
142
+ },
143
+ "set_coupon:insales:cart": {
144
+ "description": "Купон применен",
145
+ "data": "{ cart: {...}, coupon: '...' }"
146
+ },
147
+ "before:insales:cart": {
148
+ "description": "Перед любым действием с корзиной"
149
+ },
150
+ "always:insales:cart": {
151
+ "description": "После любого действия с корзиной"
152
+ }
153
+ },
154
+ "usage_priority": "data-атрибуты > события > методы"
155
+ },
156
+ "Products": {
157
+ "description": "Управление товарами",
158
+ "global_access": "window.Products",
159
+ "type": "class",
160
+ "declarative": true,
161
+ "declarative_note": "Работает полностью через data-атрибуты",
162
+ "data_attributes": {
163
+ "data-product-id": {
164
+ "required": true,
165
+ "description": "Инициализация товара (обязательно!)",
166
+ "example": "<form data-product-id=\"{{ product.id }}\">...</form>",
167
+ "note": "Все остальные атрибуты должны быть внутри этого элемента"
168
+ },
169
+ "data-product-variants": {
170
+ "description": "Селектор вариантов товара",
171
+ "example": "<select name=\"variant_id\" data-product-variants></select>",
172
+ "accepts_json": true,
173
+ "json_example": "data-product-variants='{\"default\": \"option-radio\", \"Цвет\": \"option-span\"}'",
174
+ "display_types": ["option-select", "option-radio", "option-span", "option-preview", "select-image"]
175
+ },
176
+ "data-quantity": {
177
+ "description": "Обертка для количества",
178
+ "example": "<div data-quantity><input name=\"quantity\" value=\"1\"></div>"
179
+ },
180
+ "data-quantity-change": {
181
+ "description": "Кнопки +/- для изменения количества",
182
+ "example": "<button data-quantity-change=\"-\">-</button><button data-quantity-change=\"+\">+</button>",
183
+ "no_js_needed": true
184
+ },
185
+ "data-item-add": {
186
+ "description": "Кнопка добавления в корзину",
187
+ "example": "<button type=\"submit\" data-item-add>В корзину</button>",
188
+ "no_js_needed": true
189
+ },
190
+ "data-product-card-price": {
191
+ "description": "Цена товара",
192
+ "example": "<span data-product-card-price></span>",
193
+ "auto_updates": true
194
+ },
195
+ "data-product-card-old-price": {
196
+ "description": "Старая цена",
197
+ "example": "<span data-product-card-old-price></span>",
198
+ "auto_updates": true
199
+ },
200
+ "data-product-card-sku": {
201
+ "description": "Артикул",
202
+ "example": "<span data-product-card-sku></span>",
203
+ "auto_updates": true
204
+ },
205
+ "data-product-card-available": {
206
+ "description": "Наличие товара",
207
+ "example": "<span data-product-card-available></span>",
208
+ "auto_updates": true
209
+ },
210
+ "data-product-card-sale-value": {
211
+ "description": "Размер скидки",
212
+ "example": "<span data-product-card-sale-value></span>",
213
+ "auto_updates": true
214
+ },
215
+ "data-add-cart-counter": {
216
+ "description": "Комплексный компонент счетчика корзины",
217
+ "example": "<div data-add-cart-counter>...</div>",
218
+ "complex": true
219
+ },
220
+ "data-quick-checkout": {
221
+ "description": "Быстрый заказ в один клик",
222
+ "example": "<button data-quick-checkout='[data-product-id=\"12345\"]'>Купить в 1 клик</button>",
223
+ "no_js_needed": true
224
+ },
225
+ "data-product-accessories": {
226
+ "description": "Опции товара (аксессуары)",
227
+ "example": "<div data-product-accessories></div>",
228
+ "requires_templates": true
229
+ }
230
+ },
231
+ "methods": {
232
+ "getInfo": {
233
+ "description": "Получить информацию о товаре",
234
+ "params": [{ "name": "product_id", "type": "number", "required": true }],
235
+ "returns": "Promise<Object>",
236
+ "example": "Products.getInfo(12345).then(data => console.log(data));",
237
+ "note": "Редко нужен - обычно данные уже есть в Liquid"
238
+ }
239
+ },
240
+ "events": {
241
+ "init_instance:insales:product": {
242
+ "description": "Товар инициализирован",
243
+ "data": "{ product_id, $form, variant }",
244
+ "example": "EventBus.subscribe('init_instance:insales:product', data => console.log(data));"
245
+ },
246
+ "change_variant:insales:product": {
247
+ "description": "Вариант товара изменен",
248
+ "data": "{ product_id, variant, $form }"
249
+ },
250
+ "update_variant:insales:product": {
251
+ "description": "Данные варианта обновлены",
252
+ "data": "{ product_id, variant, $form }"
253
+ },
254
+ "change_quantity:insales:product": {
255
+ "description": "Количество изменено",
256
+ "data": "{ product_id, quantity, $form }"
257
+ },
258
+ "before:insales:product": {
259
+ "description": "Перед действием"
260
+ },
261
+ "always:insales:product": {
262
+ "description": "После действия"
263
+ }
264
+ },
265
+ "css_classes": {
266
+ "with-old-price": "У варианта есть старая цена",
267
+ "without-old-price": "Нет старой цены",
268
+ "with-sku": "Есть артикул",
269
+ "without-sku": "Нет артикула",
270
+ "is-available": "Товар в наличии",
271
+ "not-available": "Нет в наличии",
272
+ "with-sale-value": "Есть скидка"
273
+ },
274
+ "usage_priority": "data-атрибуты > события > методы"
275
+ },
276
+ "EventBus": {
277
+ "description": "Шина событий для коммуникации между компонентами",
278
+ "global_access": "window.EventBus",
279
+ "type": "object",
280
+ "declarative": false,
281
+ "methods": {
282
+ "subscribe": {
283
+ "description": "Подписаться на событие",
284
+ "params": [
285
+ { "name": "event", "type": "string", "required": true },
286
+ { "name": "callback", "type": "function", "required": true }
287
+ ],
288
+ "returns": "void",
289
+ "example": "EventBus.subscribe('add_items:insales:cart', data => {\n console.log('Товар добавлен', data);\n});"
290
+ },
291
+ "publish": {
292
+ "description": "Опубликовать событие",
293
+ "params": [
294
+ { "name": "event", "type": "string", "required": true },
295
+ { "name": "data", "type": "any", "optional": true }
296
+ ],
297
+ "returns": "void",
298
+ "example": "EventBus.publish('my-event:insales:site', { foo: 'bar' });"
299
+ },
300
+ "unsubscribe": {
301
+ "description": "Отписаться от события",
302
+ "params": [
303
+ { "name": "event", "type": "string", "required": true },
304
+ { "name": "callback", "type": "function", "required": true }
305
+ ],
306
+ "returns": "void",
307
+ "example": "EventBus.unsubscribe('add_items:insales:cart', myCallback);"
308
+ }
309
+ },
310
+ "event_naming": {
311
+ "pattern": "action:namespace:module",
312
+ "examples": [
313
+ "add_items:insales:cart",
314
+ "update:insales:search",
315
+ "init-products:ui-ajax-products"
316
+ ]
317
+ },
318
+ "common_events": {
319
+ "cart": ["add_items:insales:cart", "update_items:insales:cart", "delete_items:insales:cart", "clear_items:insales:cart"],
320
+ "product": ["init_instance:insales:product", "change_variant:insales:product", "update_variant:insales:product"],
321
+ "compare": ["add_item:insales:compares", "remove_item:insales:compares", "update_items:insales:compares"],
322
+ "favorites": ["add_item:insales:favorites_products", "remove_item:insales:favorites_products", "update_items:insales:favorites_products"],
323
+ "search": ["before:insales:search", "update:insales:search", "always:insales:search"]
324
+ }
325
+ },
326
+ "Compare": {
327
+ "description": "Сравнение товаров",
328
+ "global_access": "window.Compare",
329
+ "type": "class",
330
+ "declarative": true,
331
+ "data_attributes": {
332
+ "data-compare-add": {
333
+ "description": "Добавить в сравнение",
334
+ "example": "<button data-compare-add=\"{{ product.id }}\">Сравнить</button>",
335
+ "no_js_needed": true
336
+ },
337
+ "data-compare-delete": {
338
+ "description": "Удалить из сравнения",
339
+ "example": "<button data-compare-delete=\"{{ product.id }}\">Удалить</button>",
340
+ "no_js_needed": true
341
+ },
342
+ "data-compare-trigger": {
343
+ "description": "Переключатель (добавить/удалить)",
344
+ "example": "<button data-compare-trigger=\"{{ product.id }}\">Сравнить</button>",
345
+ "no_js_needed": true,
346
+ "note": "Автоматически меняет состояние"
347
+ },
348
+ "data-compare-counter": {
349
+ "description": "Счетчик товаров в сравнении",
350
+ "example": "<span data-compare-counter></span>",
351
+ "auto_updates": true
352
+ }
353
+ },
354
+ "methods": {
355
+ "add": {
356
+ "description": "Добавить товар",
357
+ "params": [{ "name": "product_id", "type": "number", "required": true }],
358
+ "example": "Compare.add(12345);",
359
+ "note": "Обычно НЕ нужен - используйте data-compare-add"
360
+ },
361
+ "remove": {
362
+ "description": "Удалить товар",
363
+ "params": [{ "name": "product_id", "type": "number", "required": true }],
364
+ "example": "Compare.remove(12345);",
365
+ "note": "Обычно НЕ нужен - используйте data-compare-delete"
366
+ },
367
+ "update": {
368
+ "description": "Обновить состояние UI",
369
+ "example": "Compare.update();",
370
+ "note": "Нужен после AJAX-загрузки товаров"
371
+ }
372
+ },
373
+ "events": {
374
+ "add_item:insales:compares": {
375
+ "description": "Товар добавлен в сравнение",
376
+ "data": "{ product_id, items: [...] }"
377
+ },
378
+ "remove_item:insales:compares": {
379
+ "description": "Товар удален из сравнения",
380
+ "data": "{ product_id, items: [...] }"
381
+ },
382
+ "update_items:insales:compares": {
383
+ "description": "Список обновлен",
384
+ "data": "{ items: [...] }"
385
+ }
386
+ },
387
+ "usage_priority": "data-атрибуты > события > методы"
388
+ },
389
+ "FavoritesProducts": {
390
+ "description": "Избранные товары",
391
+ "global_access": "window.FavoritesProducts",
392
+ "type": "class",
393
+ "declarative": true,
394
+ "data_attributes": {
395
+ "data-ui-favorites-add": {
396
+ "description": "Добавить в избранное",
397
+ "example": "<button data-ui-favorites-add=\"{{ product.id }}\">В избранное</button>",
398
+ "no_js_needed": true
399
+ },
400
+ "data-ui-favorites-delete": {
401
+ "description": "Удалить из избранного",
402
+ "example": "<button data-ui-favorites-delete=\"{{ product.id }}\">Удалить</button>",
403
+ "no_js_needed": true
404
+ },
405
+ "data-ui-favorites-trigger": {
406
+ "description": "Переключатель (добавить/удалить)",
407
+ "example": "<button data-ui-favorites-trigger=\"{{ product.id }}\"><i class=\"icon icon-heart\"></i></button>",
408
+ "no_js_needed": true,
409
+ "note": "Автоматически меняет состояние"
410
+ },
411
+ "data-ui-favorites-counter": {
412
+ "description": "Счетчик избранных товаров",
413
+ "example": "<span data-ui-favorites-counter></span>",
414
+ "auto_updates": true
415
+ }
416
+ },
417
+ "methods": {
418
+ "add": {
419
+ "description": "Добавить товар",
420
+ "params": [{ "name": "product_id", "type": "number", "required": true }],
421
+ "example": "FavoritesProducts.add(12345);",
422
+ "note": "Обычно НЕ нужен - используйте data-ui-favorites-add"
423
+ },
424
+ "remove": {
425
+ "description": "Удалить товар",
426
+ "params": [{ "name": "product_id", "type": "number", "required": true }],
427
+ "example": "FavoritesProducts.remove(12345);",
428
+ "note": "Обычно НЕ нужен - используйте data-ui-favorites-delete"
429
+ },
430
+ "update": {
431
+ "description": "Обновить состояние UI",
432
+ "example": "FavoritesProducts.update();",
433
+ "note": "Нужен после AJAX-загрузки товаров"
434
+ }
435
+ },
436
+ "events": {
437
+ "add_item:insales:favorites_products": {
438
+ "description": "Товар добавлен в избранное",
439
+ "data": "{ product_id, items: [...] }"
440
+ },
441
+ "remove_item:insales:favorites_products": {
442
+ "description": "Товар удален из избранного",
443
+ "data": "{ product_id, items: [...] }"
444
+ },
445
+ "update_items:insales:favorites_products": {
446
+ "description": "Список обновлен",
447
+ "data": "{ items: [...] }"
448
+ }
449
+ },
450
+ "usage_priority": "data-атрибуты > события > методы"
451
+ },
452
+ "AjaxSearch": {
453
+ "description": "Живой поиск по сайту",
454
+ "global_access": "window.AjaxSearch",
455
+ "type": "class",
456
+ "declarative": true,
457
+ "data_attributes": {
458
+ "data-search-field": {
459
+ "required": true,
460
+ "description": "Поле ввода поиска",
461
+ "example": "<input type=\"text\" name=\"q\" data-search-field placeholder=\"Поиск\">",
462
+ "note": "Поиск начинается автоматически при вводе"
463
+ },
464
+ "data-search-result": {
465
+ "required": true,
466
+ "description": "Блок для результатов поиска",
467
+ "example": "<div data-search-result></div>",
468
+ "auto_updates": true
469
+ }
470
+ },
471
+ "methods": {
472
+ "setConfig": {
473
+ "description": "Настроить параметры поиска",
474
+ "params": [
475
+ { "name": "letters", "type": "number", "description": "С какого символа начинать поиск", "default": 3 },
476
+ { "name": "delay", "type": "number", "description": "Задержка между запросами (мс)", "default": 300 },
477
+ { "name": "hide_items_out_of_stock", "type": "boolean", "description": "Скрывать товары не в наличии", "default": false }
478
+ ],
479
+ "example": "AjaxSearch.setConfig({\n letters: 3,\n delay: 300,\n hide_items_out_of_stock: true\n});"
480
+ }
481
+ },
482
+ "events": {
483
+ "before:insales:search": {
484
+ "description": "Перед поиском"
485
+ },
486
+ "update:insales:search": {
487
+ "description": "Результаты обновлены",
488
+ "data": "{ products: [...], collections: [...], pages: [...] }"
489
+ },
490
+ "always:insales:search": {
491
+ "description": "После поиска"
492
+ }
493
+ },
494
+ "usage_example": "<!-- Форма поиска -->\n<form action=\"/search\" method=\"get\">\n <input type=\"hidden\" name=\"lang\" value=\"{{ language.locale }}\">\n <input type=\"text\" name=\"q\" data-search-field placeholder=\"Поиск\">\n <button type=\"submit\">Найти</button>\n <div data-search-result></div>\n</form>"
495
+ },
496
+ "ajaxAPI": {
497
+ "description": "AJAX запросы к API InSales",
498
+ "global_access": "window.ajaxAPI",
499
+ "type": "object",
500
+ "declarative": false,
501
+ "methods": {
502
+ "cart": {
503
+ "get": {
504
+ "description": "Получить корзину",
505
+ "returns": "Promise<Object>",
506
+ "example": "ajaxAPI.cart.get().then(cart => console.log(cart));"
507
+ },
508
+ "add": {
509
+ "description": "Добавить товар",
510
+ "params": [
511
+ { "name": "variant_id", "type": "number" },
512
+ { "name": "quantity", "type": "number" },
513
+ { "name": "comment", "type": "string", "optional": true }
514
+ ],
515
+ "returns": "Promise<Object>",
516
+ "example": "ajaxAPI.cart.add(12345, 2);"
517
+ },
518
+ "update": {
519
+ "description": "Обновить количество",
520
+ "params": [
521
+ { "name": "order_line_id", "type": "number" },
522
+ { "name": "quantity", "type": "number" }
523
+ ],
524
+ "returns": "Promise<Object>",
525
+ "example": "ajaxAPI.cart.update(123, 3);"
526
+ },
527
+ "remove": {
528
+ "description": "Удалить позицию",
529
+ "params": [{ "name": "order_line_id", "type": "number" }],
530
+ "returns": "Promise<Object>",
531
+ "example": "ajaxAPI.cart.remove(123);"
532
+ },
533
+ "clear": {
534
+ "description": "Очистить корзину",
535
+ "returns": "Promise<Object>",
536
+ "example": "ajaxAPI.cart.clear();"
537
+ },
538
+ "coupon": {
539
+ "description": "Применить купон",
540
+ "params": [{ "name": "coupon", "type": "string" }],
541
+ "returns": "Promise<Object>",
542
+ "example": "ajaxAPI.cart.coupon('SALE2024');"
543
+ }
544
+ },
545
+ "product": {
546
+ "get": {
547
+ "description": "Получить товар",
548
+ "params": [{ "name": "product_id", "type": "number" }],
549
+ "returns": "Promise<Object>",
550
+ "example": "ajaxAPI.product.get(12345).then(product => console.log(product));"
551
+ }
552
+ }
553
+ },
554
+ "note": "Обычно НЕ нужен - используйте Cart, Products и другие модули"
555
+ },
556
+ "Shop": {
557
+ "description": "Утилиты магазина",
558
+ "global_access": "window.Shop",
559
+ "type": "object",
560
+ "declarative": false,
561
+ "methods": {
562
+ "money_format": {
563
+ "description": "Форматировать цену",
564
+ "params": [{ "name": "price", "type": "number" }],
565
+ "returns": "string",
566
+ "example": "Shop.money_format(1234.56); // '1 234,56 ₽'"
567
+ },
568
+ "moneyWithCurrency": {
569
+ "description": "Цена с валютой",
570
+ "params": [{ "name": "price", "type": "number" }],
571
+ "returns": "string",
572
+ "example": "Shop.moneyWithCurrency(1234.56);"
573
+ }
574
+ }
575
+ },
576
+ "Template": {
577
+ "description": "Шаблонизатор",
578
+ "global_access": "window.Template",
579
+ "type": "object",
580
+ "declarative": false,
581
+ "methods": {
582
+ "render": {
583
+ "description": "Рендер шаблона",
584
+ "params": [
585
+ { "name": "data", "type": "object" },
586
+ { "name": "template", "type": "string" }
587
+ ],
588
+ "returns": "string",
589
+ "example": "Template.render({ name: 'Товар' }, '<div>{{name}}</div>');"
590
+ }
591
+ },
592
+ "note": "Редко нужен - обычно используется внутри компонентов"
593
+ }
594
+ },
595
+ "ui_components": {
596
+ "description": "UI компоненты работают через data-атрибуты и шаблоны",
597
+ "ajax_products": {
598
+ "name": "AJAX Products",
599
+ "description": "Загрузка товаров через AJAX",
600
+ "declarative": true,
601
+ "main_attributes": {
602
+ "data-ajax-products": {
603
+ "description": "Обертка компонента",
604
+ "example": "<div data-ajax-products>...</div>"
605
+ },
606
+ "data-ajax-products-list": {
607
+ "required": true,
608
+ "description": "Список товаров с настройками",
609
+ "example": "<div data-ajax-products-list='{\n \"collection\": \"new\",\n \"limit\": 20,\n \"imageResizingRules\": [...]\n}'></div>",
610
+ "settings": {
611
+ "collection": "Handle категории",
612
+ "limit": "Количество товаров",
613
+ "imageResizingRules": "Правила ресайза изображений",
614
+ "switchImages": "Загружать 2 изображения (hover)",
615
+ "shortDescriptionWordsCount": "Лимит слов в описании"
616
+ }
617
+ }
618
+ },
619
+ "initialization": {
620
+ "method": "event",
621
+ "code": "const nodes = document.querySelectorAll('[data-ajax-products-list]');\nnodes.forEach(node => {\n EventBus.publish('ui-ajax-products:load-products-list', node);\n});",
622
+ "note": "Публикуйте событие для каждого списка"
623
+ },
624
+ "events": {
625
+ "ui-ajax-products:load-products-list": {
626
+ "description": "Инициализация загрузки",
627
+ "publish": true
628
+ },
629
+ "init-products:ui-ajax-products": {
630
+ "description": "Товары загружены и отрисованы",
631
+ "subscribe": true,
632
+ "example": "EventBus.subscribe('init-products:ui-ajax-products', data => {\n // Инициализация слайдера\n FavoritesProducts.update();\n Compare.update();\n});"
633
+ }
634
+ },
635
+ "templates_required": true,
636
+ "templates": [
637
+ "data-ajax-products-list-item-template",
638
+ "data-ajax-products-list-item-image-template"
639
+ ]
640
+ },
641
+ "ajax_product": {
642
+ "name": "AJAX Product",
643
+ "description": "Загрузка одного товара через AJAX",
644
+ "declarative": true,
645
+ "main_attributes": {
646
+ "data-ajax-product": {
647
+ "required": true,
648
+ "description": "Обертка с настройками",
649
+ "example": "<div data-ajax-product='{\n \"productId\": \"12345\",\n \"productData\": [\"variants\", \"images\", \"properties\"],\n \"initOnLoadPage\": true\n}'></div>",
650
+ "settings": {
651
+ "productId": "ID товара",
652
+ "productData": "Массив данных для загрузки",
653
+ "initOnLoadPage": "Загружать при загрузке страницы",
654
+ "imageResizingRules": "Правила ресайза",
655
+ "videoBeforeImage": "Видео перед изображениями",
656
+ "videoLinksDetails": "Детали видео"
657
+ }
658
+ }
659
+ },
660
+ "product_data_options": [
661
+ "variants",
662
+ "short_description",
663
+ "description",
664
+ "price_kinds",
665
+ "first_image",
666
+ "images",
667
+ "properties",
668
+ "characteristics",
669
+ "option_names",
670
+ "bundle_info",
671
+ "video_links"
672
+ ],
673
+ "events": {
674
+ "ui-ajax-product:load-product": {
675
+ "description": "Инициализация загрузки",
676
+ "publish": true
677
+ },
678
+ "init-product:ui-ajax-product": {
679
+ "description": "Товар загружен",
680
+ "subscribe": true
681
+ }
682
+ },
683
+ "templates_required": true
684
+ },
685
+ "ajax_filters": {
686
+ "name": "AJAX Filters",
687
+ "description": "Фильтры товаров через AJAX",
688
+ "declarative": true,
689
+ "main_attributes": {
690
+ "data-ajax-filter": {
691
+ "required": true,
692
+ "description": "Форма фильтров",
693
+ "example": "<form data-ajax-filter='{\n \"useImages\": false,\n \"visibleItemsSize\": 5\n}' action=\"{{ collection.url }}\" method=\"get\">...</form>",
694
+ "settings": {
695
+ "useImages": "Использовать изображения для свойств",
696
+ "visibleItemsSize": "Количество видимых значений"
697
+ }
698
+ },
699
+ "data-ajax-filter-items": {
700
+ "required": true,
701
+ "description": "Контейнер для фильтров",
702
+ "example": "<div data-ajax-filter-items></div>"
703
+ }
704
+ },
705
+ "events": {
706
+ "init-filter:ui-ajax-filter": {
707
+ "description": "Фильтры инициализированы"
708
+ }
709
+ },
710
+ "templates_required": true,
711
+ "templates": [
712
+ "data-ajax-filter-template-price",
713
+ "data-ajax-filter-template-item",
714
+ "data-ajax-filter-template-usual",
715
+ "data-ajax-filter-template-color",
716
+ "data-ajax-filter-template-numeric"
717
+ ]
718
+ },
719
+ "accessories": {
720
+ "name": "Product Accessories",
721
+ "description": "Опции товара (аксессуары)",
722
+ "declarative": true,
723
+ "main_attributes": {
724
+ "data-product-accessories": {
725
+ "required": true,
726
+ "description": "Контейнер опций (внутри data-product-id)",
727
+ "example": "<div data-product-accessories></div>"
728
+ }
729
+ },
730
+ "events": {
731
+ "accessories-rendered:insales:ui_accessories": {
732
+ "description": "Опции отрисованы"
733
+ },
734
+ "accessory_value_changed:insales:ui_accessories": {
735
+ "description": "Опция изменена"
736
+ },
737
+ "prices-calculated:insales:ui_accessories": {
738
+ "description": "Цены пересчитаны"
739
+ }
740
+ },
741
+ "templates_required": true
742
+ },
743
+ "feedback_form": {
744
+ "name": "Feedback Form",
745
+ "description": "Форма обратной связи",
746
+ "declarative": true,
747
+ "main_attributes": {
748
+ "data-feedback-form-wrapper": {
749
+ "required": true,
750
+ "description": "Обертка формы",
751
+ "example": "<form data-feedback-form-wrapper method=\"post\" action=\"/client_account/feedback\">...</form>"
752
+ },
753
+ "data-feedback-form-field": {
754
+ "description": "Поле формы",
755
+ "example": "<input name=\"name\" data-feedback-form-field='{\"isRequired\": true, \"errorMessage\": \"Ошибка\"}'>",
756
+ "field_types": ["name", "from", "phone", "content", "subject", "agree"]
757
+ },
758
+ "data-feedback-form-success": {
759
+ "description": "Сообщение об успехе",
760
+ "example": "<div data-feedback-form-success='{\"showTime\": 10000}'>Отправлено</div>"
761
+ },
762
+ "data-feedback-form-recaptcha": {
763
+ "description": "Google reCAPTCHA",
764
+ "example": "<div data-feedback-form-recaptcha='{\"isRequired\": true}'></div>"
765
+ },
766
+ "data-feedback-form-yandex-captcha": {
767
+ "description": "Yandex SmartCaptcha",
768
+ "example": "<div data-feedback-form-yandex-captcha='{\"isRequired\": true}'></div>"
769
+ }
770
+ },
771
+ "events": {
772
+ "send-feedback:insales:ui_feedback": {
773
+ "description": "Форма отправлена"
774
+ },
775
+ "error-feedback:insales:ui_feedback": {
776
+ "description": "Ошибка отправки"
777
+ },
778
+ "show-modal-feedback:insales:ui_feedback": {
779
+ "description": "Показать модальное окно"
780
+ }
781
+ },
782
+ "no_js_needed": true
783
+ },
784
+ "reviews_form": {
785
+ "name": "Reviews Form",
786
+ "description": "Форма отзыва к товару",
787
+ "declarative": true,
788
+ "main_attributes": {
789
+ "data-reviews-form-wrapper": {
790
+ "required": true,
791
+ "description": "Обертка формы отзыва",
792
+ "example": "<form data-reviews-form-wrapper='{\n \"reviews_moderated\": true,\n \"url\": \"{{ product.url }}\"\n}'>...</form>"
793
+ },
794
+ "data-reviews-form-field": {
795
+ "description": "Поле формы",
796
+ "field_types": ["review[author]", "review[email]", "review[content]", "review[rating]", "review[image_attributes][image]"]
797
+ }
798
+ },
799
+ "events": {
800
+ "send-review:insales:ui_reviews": {
801
+ "description": "Отзыв отправлен"
802
+ },
803
+ "error-reviews:insales:ui_reviews": {
804
+ "description": "Ошибка отправки"
805
+ }
806
+ },
807
+ "no_js_needed": true
808
+ },
809
+ "comments_form": {
810
+ "name": "Comments Form",
811
+ "description": "Форма комментария к статье",
812
+ "declarative": true,
813
+ "main_attributes": {
814
+ "data-comments-form-wrapper": {
815
+ "required": true,
816
+ "description": "Обертка формы комментария",
817
+ "example": "<form data-comments-form-wrapper='{\n \"reviews_moderated\": true,\n \"url\": \"{{ article.url }}\"\n}'>...</form>"
818
+ },
819
+ "data-comments-form-field": {
820
+ "description": "Поле формы",
821
+ "field_types": ["comment[author]", "comment[email]", "comment[content]"]
822
+ }
823
+ },
824
+ "events": {
825
+ "send-comment:insales:ui_comments": {
826
+ "description": "Комментарий отправлен"
827
+ },
828
+ "error-comments:insales:ui_comments": {
829
+ "description": "Ошибка отправки"
830
+ }
831
+ },
832
+ "no_js_needed": true
833
+ },
834
+ "quick_checkout": {
835
+ "name": "Quick Checkout",
836
+ "description": "Быстрый заказ / заявка",
837
+ "declarative": true,
838
+ "main_attributes": {
839
+ "data-quick-checkout": {
840
+ "required": true,
841
+ "description": "Кнопка быстрого заказа",
842
+ "example": "<button data-quick-checkout='[data-product-id=\"12345\"]'>Купить в 1 клик</button>",
843
+ "variants": {
844
+ "with_product": "data-quick-checkout='[data-product-id=\"12345\"]'",
845
+ "fake_order": "data-quick-checkout='fake_order'",
846
+ "service_form": "data-quick-checkout-modal-handle=\"service\""
847
+ }
848
+ }
849
+ },
850
+ "no_js_needed": true,
851
+ "note": "Форма отдается сервером, только активация через кнопку"
852
+ },
853
+ "trigger_events": {
854
+ "name": "Trigger Events",
855
+ "description": "Публикация событий по клику",
856
+ "declarative": true,
857
+ "main_attributes": {
858
+ "data-trigger-click": {
859
+ "required": true,
860
+ "description": "Публиковать событие при клике",
861
+ "example": "<button data-trigger-click=\"my-button:insales:site\">Кнопка</button>",
862
+ "usage": "EventBus.subscribe('my-button:insales:site', data => {\n console.log('Клик', data.event_target);\n});"
863
+ }
864
+ },
865
+ "no_js_needed": false,
866
+ "note": "Требует подписки на событие в JS"
867
+ }
868
+ },
869
+ "best_practices": {
870
+ "declarative_first": {
871
+ "title": "Приоритет декларативному подходу",
872
+ "rules": [
873
+ "Всегда используйте data-атрибуты вместо JavaScript где возможно",
874
+ "Пишите минимум JS кода - библиотека создана для этого",
875
+ "Подписывайтесь на события вместо вызова методов",
876
+ "Используйте шаблоны для динамического контента"
877
+ ]
878
+ },
879
+ "no_imports": {
880
+ "title": "Не используйте import",
881
+ "wrong": "import { Cart } from 'common-js'; // ❌ НЕПРАВИЛЬНО",
882
+ "correct": "// ✅ ПРАВИЛЬНО - модули уже доступны глобально\nCart.add(12345, 1);",
883
+ "note": "Все модули доступны через window после подключения библиотеки"
884
+ },
885
+ "event_driven": {
886
+ "title": "Событийная архитектура",
887
+ "description": "Используйте EventBus для коммуникации между компонентами",
888
+ "example": "// Подписка на добавление в корзину\nEventBus.subscribe('add_items:insales:cart', data => {\n console.log('Товар добавлен', data);\n // Показать уведомление\n // Обновить счетчик\n});"
889
+ },
890
+ "minimal_js_examples": {
891
+ "title": "Примеры без JavaScript",
892
+ "examples": [
893
+ {
894
+ "task": "Добавить товар в корзину",
895
+ "html": "<form data-product-id=\"{{ product.id }}\">\n <button type=\"submit\" data-item-add>В корзину</button>\n</form>",
896
+ "js_needed": false,
897
+ "note": "Работает полностью без JS"
898
+ },
899
+ {
900
+ "task": "Удалить из корзины",
901
+ "html": "<button data-item-delete>Удалить</button>",
902
+ "js_needed": false
903
+ },
904
+ {
905
+ "task": "Добавить в избранное",
906
+ "html": "<button data-ui-favorites-trigger=\"{{ product.id }}\">\n <i class=\"icon icon-heart\"></i>\n</button>",
907
+ "js_needed": false
908
+ },
909
+ {
910
+ "task": "Быстрый заказ",
911
+ "html": "<button data-quick-checkout='[data-product-id=\"{{ product.id }}\"]'>\n Купить в 1 клик\n</button>",
912
+ "js_needed": false
913
+ }
914
+ ]
915
+ },
916
+ "when_js_needed": {
917
+ "title": "Когда нужен JavaScript",
918
+ "cases": [
919
+ {
920
+ "case": "Реакция на события",
921
+ "example": "EventBus.subscribe('add_items:insales:cart', data => {\n // Показать уведомление\n showNotification('Товар добавлен');\n});"
922
+ },
923
+ {
924
+ "case": "Обновление UI после AJAX-загрузки",
925
+ "example": "EventBus.subscribe('init-products:ui-ajax-products', data => {\n FavoritesProducts.update();\n Compare.update();\n // Инициализация слайдера\n});"
926
+ },
927
+ {
928
+ "case": "Кастомная логика",
929
+ "example": "EventBus.subscribe('change_variant:insales:product', data => {\n // Кастомная обработка смены варианта\n});"
930
+ }
931
+ ]
932
+ }
933
+ },
934
+ "common_patterns": {
935
+ "product_card": {
936
+ "title": "Карточка товара",
937
+ "html": "<form data-product-id=\"{{ product.id }}\" action=\"{{ cart_url }}\" method=\"post\">\n <input type=\"hidden\" name=\"variant_id\" value=\"{{ product.variants.first.id }}\">\n \n <!-- Цена -->\n <div class=\"price\">\n <span data-product-card-price></span>\n <span data-product-card-old-price></span>\n </div>\n \n <!-- Варианты -->\n <select name=\"variant_id\" data-product-variants></select>\n \n <!-- Количество -->\n <div data-quantity>\n <button data-quantity-change=\"-\">-</button>\n <input name=\"quantity\" value=\"1\">\n <button data-quantity-change=\"+\">+</button>\n </div>\n \n <!-- Кнопки -->\n <button type=\"submit\" data-item-add>В корзину</button>\n <button data-ui-favorites-trigger=\"{{ product.id }}\">\n <i class=\"icon icon-heart\"></i>\n </button>\n</form>",
938
+ "js_needed": false,
939
+ "note": "Полностью работает без JavaScript"
940
+ },
941
+ "cart_page": {
942
+ "title": "Страница корзины",
943
+ "html": "<form data-cart-form action=\"{{ cart_url }}\" method=\"post\">\n {% for item in cart.order_lines %}\n <div data-item-id=\"{{ item.id }}\">\n <div>{{ item.title }}</div>\n <input name=\"order_line[{{ item.id }}][quantity]\" value=\"{{ item.quantity }}\">\n <span data-product-card-price></span>\n <button data-item-delete>Удалить</button>\n </div>\n {% endfor %}\n \n <div>Итого: <span data-cart-total-price></span></div>\n <button type=\"submit\">Оформить заказ</button>\n <button data-cart-clear>Очистить корзину</button>\n</form>",
944
+ "js_needed": false
945
+ },
946
+ "ajax_products_list": {
947
+ "title": "AJAX список товаров",
948
+ "html": "<div data-ajax-products>\n <div data-ajax-products-list='{\n \"collection\": \"new\",\n \"limit\": 12,\n \"imageResizingRules\": [\n {\"size\":\"600\", \"format\":\"webp\", \"resizing_type\":\"fit_width\", \"quality\":\"90\"}\n ]\n }'></div>\n \n <template data-ajax-products-list-item-template>\n <div data-ajax-products-list-item>\n <form data-ajax-products-list-item-form>\n <a data-ajax-products-list-item-link data-ajax-products-list-item-title></a>\n <div data-ajax-products-list-item-image></div>\n <span data-ajax-products-list-item-price-min></span>\n <button type=\"submit\" data-item-add>В корзину</button>\n </form>\n </div>\n </template>\n \n <template data-ajax-products-list-item-image-template>\n <picture data-ajax-products-list-item-picture>\n <img data-ajax-products-image-resizing-rules-index=\"0\">\n </picture>\n </template>\n</div>",
949
+ "js": "const nodes = document.querySelectorAll('[data-ajax-products-list]');\nnodes.forEach(node => {\n EventBus.publish('ui-ajax-products:load-products-list', node);\n});\n\n// После загрузки\nEventBus.subscribe('init-products:ui-ajax-products', data => {\n FavoritesProducts.update();\n Compare.update();\n});",
950
+ "js_needed": true,
951
+ "note": "Требует инициализации через EventBus"
952
+ },
953
+ "live_search": {
954
+ "title": "Живой поиск",
955
+ "html": "<form action=\"/search\" method=\"get\">\n <input type=\"hidden\" name=\"lang\" value=\"{{ language.locale }}\">\n <input type=\"text\" name=\"q\" data-search-field placeholder=\"Поиск\">\n <button type=\"submit\">Найти</button>\n <div data-search-result></div>\n</form>",
956
+ "js_needed": false,
957
+ "note": "Работает автоматически"
958
+ }
959
+ },
960
+ "troubleshooting": {
961
+ "import_error": {
962
+ "problem": "Ошибка: Cannot find module 'common-js'",
963
+ "solution": "НЕ используйте import! Все модули доступны глобально через window",
964
+ "correct_usage": "// Просто используйте модули напрямую\nCart.add(12345, 1);\nEventBus.subscribe('add_items:insales:cart', callback);"
965
+ },
966
+ "lodash_error": {
967
+ "problem": "Ошибка: _ is not defined",
968
+ "solution": "Lodash НЕ глобальный. Используйте нативный JavaScript или jQuery",
969
+ "alternatives": [
970
+ "Array.prototype.map/filter/reduce вместо _.map/_.filter",
971
+ "Object.keys/values/entries вместо _.keys/_.values",
972
+ "jQuery методы: $.each, $.map, $.extend"
973
+ ]
974
+ },
975
+ "data_attribute_not_working": {
976
+ "problem": "data-атрибут не работает",
977
+ "checklist": [
978
+ "Проверьте что библиотека подключена: {% include_insales_scripts \"common-js@v2\" %}",
979
+ "Убедитесь что атрибут написан правильно (регистр важен)",
980
+ "Для товаров: data-атрибуты должны быть внутри data-product-id",
981
+ "Для корзины: data-атрибуты должны быть внутри data-cart-form",
982
+ "Проверьте консоль браузера на ошибки"
983
+ ]
984
+ },
985
+ "ajax_products_not_loading": {
986
+ "problem": "AJAX товары не загружаются",
987
+ "solution": "Нужно опубликовать событие инициализации",
988
+ "code": "const nodes = document.querySelectorAll('[data-ajax-products-list]');\nnodes.forEach(node => {\n EventBus.publish('ui-ajax-products:load-products-list', node);\n});"
989
+ }
990
+ },
991
+ "migration_from_old_approach": {
992
+ "title": "Миграция со старого подхода",
993
+ "before": {
994
+ "description": "Старый подход с импортами (НЕПРАВИЛЬНО)",
995
+ "code": "import { Cart } from 'common-js';\nimport { Products } from 'common-js';\n\nCart.add(12345, 1);"
996
+ },
997
+ "after": {
998
+ "description": "Новый подход - глобальные модули (ПРАВИЛЬНО)",
999
+ "code": "// Модули уже доступны глобально\n// Просто используйте их:\n\nCart.add(12345, 1);\nProducts.getInfo(12345);\nEventBus.subscribe('add_items:insales:cart', callback);"
1000
+ },
1001
+ "best_approach": {
1002
+ "description": "Лучший подход - декларативный (ИДЕАЛЬНО)",
1003
+ "html": "<!-- БЕЗ JavaScript -->\n<form data-product-id=\"{{ product.id }}\">\n <button type=\"submit\" data-item-add>В корзину</button>\n</form>",
1004
+ "js": "// Только если нужна реакция на событие\nEventBus.subscribe('add_items:insales:cart', data => {\n showNotification('Товар добавлен');\n});"
1005
+ }
1006
+ },
1007
+ "quick_reference": {
1008
+ "title": "Быстрая справка",
1009
+ "most_used_attributes": [
1010
+ "data-product-id - инициализация товара",
1011
+ "data-item-add - добавить в корзину",
1012
+ "data-cart-form - форма корзины",
1013
+ "data-item-delete - удалить из корзины",
1014
+ "data-ui-favorites-trigger - избранное",
1015
+ "data-compare-trigger - сравнение",
1016
+ "data-search-field - поиск",
1017
+ "data-quick-checkout - быстрый заказ"
1018
+ ],
1019
+ "most_used_events": [
1020
+ "add_items:insales:cart - товар добавлен",
1021
+ "change_variant:insales:product - вариант изменен",
1022
+ "update:insales:search - результаты поиска",
1023
+ "init-products:ui-ajax-products - AJAX товары загружены"
1024
+ ],
1025
+ "global_modules_list": [
1026
+ "Cart - корзина",
1027
+ "Products - товары",
1028
+ "EventBus - события",
1029
+ "Compare - сравнение",
1030
+ "FavoritesProducts - избранное",
1031
+ "AjaxSearch - поиск",
1032
+ "ajaxAPI - AJAX запросы",
1033
+ "Shop - утилиты",
1034
+ "Template - шаблоны"
1035
+ ]
1036
+ }
1037
+ }