fixed many problems + resolved #21
This commit is contained in:
parent
557eebc91f
commit
ae866d8ddb
|
@ -85,6 +85,31 @@ final class cart extends core
|
|||
'products' => $this->cart?->products(language: $this->language, currency: $this->currency)
|
||||
];
|
||||
|
||||
if (!empty($this->view->cart['products'])) {
|
||||
// Initialized products
|
||||
|
||||
// Declaring buffer of formatted products
|
||||
$formatted = [];
|
||||
|
||||
foreach ($this->view->cart['products'] as $product) {
|
||||
// Iterating over products
|
||||
|
||||
// Formatting products
|
||||
for ($i = 0; $i < $product['amount']; ++$i) {
|
||||
$formatted[] = [
|
||||
'weight' => $product['document']['weight'] ?? 0,
|
||||
...$product['document']['dimensions']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($product);
|
||||
|
||||
// Initializing formatted products
|
||||
$this->view->formatted = $formatted;
|
||||
}
|
||||
|
||||
// Initializing types of avaiabld deliveries
|
||||
$this->view->deliveries = [
|
||||
'cdek' => [
|
||||
|
@ -319,8 +344,33 @@ final class cart extends core
|
|||
if ($this->cart instanceof model) {
|
||||
// Initialized the cart
|
||||
|
||||
// Initializing summary data of the cart
|
||||
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
||||
// Initializing products in the cart
|
||||
$products = $this->cart->products(language: $this->language, currency: $this->currency);
|
||||
|
||||
if (!empty($products)) {
|
||||
// Initialized products
|
||||
|
||||
// Initializing summary data of the cart
|
||||
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
||||
|
||||
// Declaring buffer of formatted products
|
||||
$formatted = [];
|
||||
|
||||
foreach ($products as $product) {
|
||||
// Iterating over products
|
||||
|
||||
// Formatting products
|
||||
for ($i = 0; $i < $product['amount']; ++$i) {
|
||||
$formatted[] = [
|
||||
'weight' => $product['document']['weight'] ?? 0,
|
||||
...$product['document']['dimensions']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($product);
|
||||
|
||||
// Sending response
|
||||
$this->response
|
||||
|
@ -330,6 +380,7 @@ final class cart extends core
|
|||
->json([
|
||||
'cost' => $summary['cost'] ?? 0,
|
||||
'amount' => $summary['amount'] ?? 0,
|
||||
'products' => $formatted ?? [],
|
||||
'errors' => $this->errors
|
||||
])
|
||||
->validate($this->request)
|
||||
|
|
|
@ -148,7 +148,7 @@ final class catalog extends core
|
|||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: ['catalog_filters_brand' => $brand ?? null]));
|
||||
|
||||
// Writing to the current implementator of the buffer
|
||||
$this->session->buffer = ['catalog' => ['filters' => ['brand' => $brand ?? null]]] + $this->session->buffer ?? [];
|
||||
$this->session->buffer = ['catalog' => ['filters' => ['brand' => $brand ?? null]]] + ($this->session->buffer ?? []);
|
||||
|
||||
// Initialize buffer of filters query (AQL)
|
||||
$_sort = 'd.position ASC, d.name ASC, d.created DESC';
|
||||
|
|
|
@ -58,8 +58,9 @@ final class delivery extends core
|
|||
* Validate and write delivery data to account and session buffers
|
||||
*
|
||||
* @param string|null $company Name of delivery company
|
||||
* @param ?string $location location
|
||||
* @param ?string $street Address with street and house
|
||||
* @param string|null $location Location (city)
|
||||
* @param string|null $street Address (street with house)
|
||||
* @param string|int|null $type Type or taruff
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
|
@ -68,7 +69,8 @@ final class delivery extends core
|
|||
string|null $company = null,
|
||||
/* string|location|null $location = null, */
|
||||
?string $location = null,
|
||||
?string $street = null
|
||||
?string $street = null,
|
||||
string|int|null $type = null
|
||||
): null {
|
||||
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
||||
// Request for JSON response
|
||||
|
@ -102,6 +104,53 @@ final class delivery extends core
|
|||
// Writing to the buffer of the response
|
||||
/* $response['company'] = $normalized; */
|
||||
|
||||
// Initializing the cart
|
||||
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
||||
|
||||
if ($this->cart instanceof cart) {
|
||||
// Initialized the cart
|
||||
|
||||
// Initializing products in the cart
|
||||
$products = $this->cart->products(language: $this->language, currency: $this->currency);
|
||||
|
||||
// Declaring buffer of formatted products
|
||||
$formatted = [];
|
||||
|
||||
if (!empty($products)) {
|
||||
// Initialized products
|
||||
|
||||
foreach ($products as $product) {
|
||||
// Iterating over products
|
||||
|
||||
// Formatting products
|
||||
for ($i = 0; $i < $product['amount']; ++$i) {
|
||||
$formatted[] = [
|
||||
'weight' => $product['document']['weight'] ?? 0,
|
||||
...$product['document']['dimensions']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($product);
|
||||
|
||||
// Writing delivery section to the buffer of the response (@todo add check for exists)
|
||||
$response['delivery'] = [
|
||||
'html' => $this->view->render('cart/elements/deliveries/' . $normalized . '/section.html'),
|
||||
'javascript' => match ($normalized) {
|
||||
'cdek' => [
|
||||
[
|
||||
'code' => $this->view->render('cart/elements/deliveries/' . $normalized . '/javascript.html', [
|
||||
'formatted' => $formatted
|
||||
])
|
||||
]
|
||||
],
|
||||
default => null
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// Initialization buffer of delivery parameters
|
||||
$delivery = $this->account?->buffer['delivery'] ?? $this->session?->buffer['delivery'] ?? [];
|
||||
|
||||
|
@ -174,7 +223,6 @@ final class delivery extends core
|
|||
$locations = null;
|
||||
|
||||
if ($delivery['company'] === 'cdek') {
|
||||
// Delivery by CDEK
|
||||
|
||||
// Searching for locations by name (first part with spaces before first comma or any non word symbol)
|
||||
$cdek = cdek::location($normalized[0], $this->errors['delivery'])?->items;
|
||||
|
@ -250,42 +298,45 @@ final class delivery extends core
|
|||
// Reinitializating locations from buffer of validated locations by input values
|
||||
$locations = $buffer;
|
||||
|
||||
if (count($locations) === 1) {
|
||||
// Identificated location
|
||||
/* if (count($locations) === 1) { */
|
||||
// Identificated location
|
||||
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [$name = 'delivery_' . $delivery['company'] . '_location' => $locations[0]]));
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [$name = 'delivery_' . $delivery['company'] . '_location' => $locations[0]]));
|
||||
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [$name => $locations[0]]));
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [$name => $locations[0]]));
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name);
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name);
|
||||
|
||||
// Writing result value of location name
|
||||
$result = $locations[0]['name'] . ', ' . implode(', ', array_reverse($locations[0]['structure']));
|
||||
// Writing result value of location name
|
||||
$result = $locations[0]['name'] . ', ' . implode(', ', array_reverse($locations[0]['structure']));
|
||||
|
||||
// Writing location data to the buffer of the response
|
||||
/* $response['location'] = [
|
||||
// Writing location data to the buffer of the response
|
||||
/* $response['location'] = [
|
||||
'identifier' => $locations[0]['identifier'],
|
||||
'input' => $result
|
||||
]; */
|
||||
|
||||
if (!empty($delivery[$delivery['company']]['street'])) {
|
||||
// Required parameters initialized: company, location, street
|
||||
// Writing status of execution to the buffer of the response
|
||||
$response['status'] = 'success';
|
||||
|
||||
// Writing readiness status to the buffer of the response
|
||||
$response['ready'] = true;
|
||||
if (!empty($delivery[$delivery['company']]['street'])) {
|
||||
// Required parameters initialized: company, location, street
|
||||
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [$name = 'delivery_' . $delivery['company'] . '_ready' => true]));
|
||||
// Writing readiness status to the buffer of the response
|
||||
$response['ready'] = true;
|
||||
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [$name => true]));
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [$name = 'delivery_' . $delivery['company'] . '_ready' => true]));
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name);
|
||||
} else {
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [$name => true]));
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name);
|
||||
/* } else {
|
||||
// Not initialized required parameters
|
||||
|
||||
// Writing to the session buffer
|
||||
|
@ -304,10 +355,7 @@ final class delivery extends core
|
|||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name_ready, $name_cost, $name_days);
|
||||
}
|
||||
|
||||
// Writing status of execution to the buffer of the response
|
||||
$response['status'] = 'success';
|
||||
} */
|
||||
|
||||
// Writing locations into response buffer
|
||||
$response['locations'] = [];
|
||||
|
@ -428,7 +476,7 @@ final class delivery extends core
|
|||
$normalized = '';
|
||||
|
||||
// Normalizing street
|
||||
if (preg_match('/[\w\d\s]+/u', urldecode($street), $matches)) $normalized = mb_ucfirst($matches[0] ?? '');
|
||||
if (preg_match('/[\w\d\s\.\,]+/u', urldecode($street), $matches)) $normalized = mb_ucfirst($matches[0] ?? '');
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($matches);
|
||||
|
@ -502,6 +550,79 @@ final class delivery extends core
|
|||
// Deinitializing unnecessary variables
|
||||
unset($normalized);
|
||||
}
|
||||
} else if (isset($type)) {
|
||||
// Received delivery type
|
||||
|
||||
if ((is_string($type) && mb_strlen($type) < 30) || (is_int($type && $type < 10000))) {
|
||||
// Validated delivery type
|
||||
|
||||
// Declating variable for result value of delivery type
|
||||
$result = '';
|
||||
|
||||
// Declating variable for normalized value of delivery type
|
||||
$normalized = '';
|
||||
|
||||
// Normalizing location name
|
||||
if (preg_match('/[\w\d]+/', trim(urldecode($type)), $matches)) $normalized = $matches[0];
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($matches);
|
||||
|
||||
// Initialization buffer of delivery parameters
|
||||
$delivery = $this->account?->buffer['delivery'] ?? $this->session?->buffer['delivery'] ?? [];
|
||||
|
||||
if (isset($delivery['company'])) {
|
||||
// Initialized delivery company
|
||||
|
||||
if (!empty($normalized)) {
|
||||
// Normalized delivery type
|
||||
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [$name = 'delivery_' . $delivery['company'] . '_type' => $normalized]));
|
||||
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [$name => $normalized]));
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name);
|
||||
|
||||
// Writing result value of delivery type
|
||||
$result = $normalized;
|
||||
|
||||
// Writing status of execution to the buffer of the response
|
||||
$response['status'] = 'success';
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($normalized);
|
||||
} else {
|
||||
// Value is empty after separating
|
||||
|
||||
// Not initialized required parameters
|
||||
|
||||
// Writing to the session buffer
|
||||
$this->core->request(new request('PATCH', '/session/write', protocol::http_3, parameters: [
|
||||
$name_type = 'delivery_' . $delivery['company'] . '_type' => null,
|
||||
$name_ready = 'delivery_' . $delivery['company'] . '_ready' => false,
|
||||
$name_cost = 'delivery_' . $delivery['company'] . '_cost' => null,
|
||||
$name_days = 'delivery_' . $delivery['company'] . '_days' => null
|
||||
]));
|
||||
|
||||
// Writing to the account buffer
|
||||
$this->core->request(new request('PATCH', '/account/write', protocol::http_3, parameters: [
|
||||
$name_type => null,
|
||||
$name_ready => false,
|
||||
$name_cost => null,
|
||||
$name_days => null
|
||||
]));
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($name_type, $name_ready, $name_cost, $name_days);
|
||||
}
|
||||
}
|
||||
|
||||
// Deinitializing unnecessary variables
|
||||
unset($delivery, $location, $result, $normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Sending response
|
||||
|
@ -588,8 +709,7 @@ final class delivery extends core
|
|||
from_street: 'Екатерининская 116', // @todo issues #13
|
||||
to_location: $delivery[$delivery['company']]['location']['identifier'],
|
||||
to_street: $delivery[$delivery['company']]['street'],
|
||||
tariff: 368, // ИМ : warehouse-terminal (склад-постамат)
|
||||
// tariff: 486, // Обычная доставка : warehouse-terminal (склад-постамат)
|
||||
tariff: $delivery[$delivery['company']]['type'] ?? 368,
|
||||
products: $formatted,
|
||||
date: new datetime(), // @todo weekdays only? + timezones
|
||||
errors: $this->errors['delivery']
|
||||
|
@ -636,12 +756,15 @@ final class delivery extends core
|
|||
],
|
||||
'street' => $delivery[$delivery['company']]['street'],
|
||||
'cost' => $cdek->total_sum,
|
||||
'days' => $cdek->calendar_max
|
||||
'days' => $cdek->calendar_max,
|
||||
'type' => $delivery[$delivery['company']]['type'] ?? 368,
|
||||
]], $this->errors['buffer']);
|
||||
|
||||
// Writing to response buffer
|
||||
$response['cost'] = $cdek->total_sum;
|
||||
$response['days'] = $cdek->calendar_max;
|
||||
$response['longitude'] = $delivery[$delivery['company']]['location']['data']['longitude'];
|
||||
$response['latitude'] = $delivery[$delivery['company']]['location']['data']['latitude'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,10 +268,12 @@ final class session extends core implements document_interface, collection_inter
|
|||
<<<'AQL'
|
||||
FOR d IN @@collection
|
||||
FILTER d.address == @address && d.expires > @time && d.active == true
|
||||
SORT d.updated DESC
|
||||
LIMIT 1
|
||||
RETURN d
|
||||
AQL,
|
||||
[
|
||||
'@collection' => static::COLLECTION,
|
||||
'@collection' => static::COLLECTION,
|
||||
'address' => $address,
|
||||
'time' => time()
|
||||
],
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
<?php
|
||||
|
||||
define('SETTINGS', realpath('..' . DIRECTORY_SEPARATOR . 'settings'));
|
||||
define('CDEK', require(SETTINGS . DIRECTORY_SEPARATOR . 'deliveries' . DIRECTORY_SEPARATOR . 'cdek.php'));
|
||||
|
||||
$service = new service(
|
||||
/**
|
||||
* Вставьте свой аккаунт\идентификатор для интеграции
|
||||
* Put your account for integration here
|
||||
*/
|
||||
CDEK['account'],
|
||||
|
||||
/**
|
||||
* Вставьте свой пароль для интеграции
|
||||
* Put your password for integration here
|
||||
*/
|
||||
CDEK['secret']
|
||||
);
|
||||
|
||||
$service->process($_GET, file_get_contents('php://input'));
|
||||
|
||||
class service
|
||||
{
|
||||
/**
|
||||
* @var string Auth login
|
||||
*/
|
||||
private $login;
|
||||
/**
|
||||
* @var string Auth pwd
|
||||
*/
|
||||
private $secret;
|
||||
/**
|
||||
* @var string Base Url for API 2.0 Production
|
||||
*/
|
||||
private $baseUrl;
|
||||
/**
|
||||
* @var string Auth Token
|
||||
*/
|
||||
private $authToken;
|
||||
/**
|
||||
* @var array Data From Request
|
||||
*/
|
||||
private $requestData;
|
||||
/** @var array Request metrics */
|
||||
private $metrics;
|
||||
|
||||
public function __construct($login, $secret, $baseUrl = 'https://api.cdek.ru/v2')
|
||||
{
|
||||
$this->login = $login;
|
||||
$this->secret = $secret;
|
||||
$this->baseUrl = $baseUrl;
|
||||
$this->metrics = array();
|
||||
}
|
||||
|
||||
public function process($requestData, $body)
|
||||
{
|
||||
$time = $this->startMetrics();
|
||||
|
||||
$this->requestData = array_merge($requestData, json_decode($body, true) ?: array());
|
||||
|
||||
if (!isset($this->requestData['action'])) {
|
||||
$this->sendValidationError('Action is required');
|
||||
}
|
||||
|
||||
$this->getAuthToken();
|
||||
|
||||
switch ($this->requestData['action']) {
|
||||
case 'offices':
|
||||
$this->sendResponse($this->getOffices(), $time);
|
||||
break;
|
||||
case 'calculate':
|
||||
$this->sendResponse($this->calculate(), $time);
|
||||
break;
|
||||
default:
|
||||
$this->sendValidationError('Unknown action');
|
||||
}
|
||||
}
|
||||
|
||||
private function sendValidationError($message)
|
||||
{
|
||||
$this->http_response_code(400);
|
||||
header('Content-Type: application/json');
|
||||
header('X-Service-Version: 3.11.1');
|
||||
echo json_encode(array('message' => $message));
|
||||
exit();
|
||||
}
|
||||
|
||||
private function http_response_code($code)
|
||||
{
|
||||
switch ($code) {
|
||||
case 100:
|
||||
$text = 'Continue';
|
||||
break;
|
||||
case 101:
|
||||
$text = 'Switching Protocols';
|
||||
break;
|
||||
case 200:
|
||||
$text = 'OK';
|
||||
break;
|
||||
case 201:
|
||||
$text = 'Created';
|
||||
break;
|
||||
case 202:
|
||||
$text = 'Accepted';
|
||||
break;
|
||||
case 203:
|
||||
$text = 'Non-Authoritative Information';
|
||||
break;
|
||||
case 204:
|
||||
$text = 'No Content';
|
||||
break;
|
||||
case 205:
|
||||
$text = 'Reset Content';
|
||||
break;
|
||||
case 206:
|
||||
$text = 'Partial Content';
|
||||
break;
|
||||
case 300:
|
||||
$text = 'Multiple Choices';
|
||||
break;
|
||||
case 301:
|
||||
$text = 'Moved Permanently';
|
||||
break;
|
||||
case 302:
|
||||
$text = 'Moved Temporarily';
|
||||
break;
|
||||
case 303:
|
||||
$text = 'See Other';
|
||||
break;
|
||||
case 304:
|
||||
$text = 'Not Modified';
|
||||
break;
|
||||
case 305:
|
||||
$text = 'Use Proxy';
|
||||
break;
|
||||
case 400:
|
||||
$text = 'Bad Request';
|
||||
break;
|
||||
case 401:
|
||||
$text = 'Unauthorized';
|
||||
break;
|
||||
case 402:
|
||||
$text = 'Payment Required';
|
||||
break;
|
||||
case 403:
|
||||
$text = 'Forbidden';
|
||||
break;
|
||||
case 404:
|
||||
$text = 'Not Found';
|
||||
break;
|
||||
case 405:
|
||||
$text = 'Method Not Allowed';
|
||||
break;
|
||||
case 406:
|
||||
$text = 'Not Acceptable';
|
||||
break;
|
||||
case 407:
|
||||
$text = 'Proxy Authentication Required';
|
||||
break;
|
||||
case 408:
|
||||
$text = 'Request Time-out';
|
||||
break;
|
||||
case 409:
|
||||
$text = 'Conflict';
|
||||
break;
|
||||
case 410:
|
||||
$text = 'Gone';
|
||||
break;
|
||||
case 411:
|
||||
$text = 'Length Required';
|
||||
break;
|
||||
case 412:
|
||||
$text = 'Precondition Failed';
|
||||
break;
|
||||
case 413:
|
||||
$text = 'Request Entity Too Large';
|
||||
break;
|
||||
case 414:
|
||||
$text = 'Request-URI Too Large';
|
||||
break;
|
||||
case 415:
|
||||
$text = 'Unsupported Media Type';
|
||||
break;
|
||||
case 500:
|
||||
$text = 'Internal Server Error';
|
||||
break;
|
||||
case 501:
|
||||
$text = 'Not Implemented';
|
||||
break;
|
||||
case 502:
|
||||
$text = 'Bad Gateway';
|
||||
break;
|
||||
case 503:
|
||||
$text = 'Service Unavailable';
|
||||
break;
|
||||
case 504:
|
||||
$text = 'Gateway Time-out';
|
||||
break;
|
||||
case 505:
|
||||
$text = 'HTTP Version not supported';
|
||||
break;
|
||||
default:
|
||||
exit('Unknown http status code "' . htmlentities($code) . '"');
|
||||
}
|
||||
|
||||
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
|
||||
header($protocol . ' ' . $code . ' ' . $text);
|
||||
$GLOBALS['http_response_code'] = $code;
|
||||
}
|
||||
|
||||
private function getAuthToken()
|
||||
{
|
||||
$time = $this->startMetrics();
|
||||
|
||||
$token = $this->httpRequest('oauth/token', array(
|
||||
'grant_type' => 'client_credentials',
|
||||
'client_id' => $this->login,
|
||||
'client_secret' => $this->secret,
|
||||
), true);
|
||||
|
||||
$this->endMetrics('auth', 'Server Auth Time', $time);
|
||||
|
||||
$result = json_decode($token['result'], true);
|
||||
|
||||
if (!isset($result['access_token'])) {
|
||||
throw new RuntimeException('Server not authorized to CDEK API');
|
||||
}
|
||||
|
||||
$this->authToken = $result['access_token'];
|
||||
}
|
||||
|
||||
private function startMetrics()
|
||||
{
|
||||
return function_exists('hrtime') ? hrtime(true) : microtime(true);
|
||||
}
|
||||
|
||||
private function httpRequest($method, $data, $useFormData = false, $useJson = false)
|
||||
{
|
||||
$ch = curl_init("$this->baseUrl/$method");
|
||||
|
||||
$headers = array(
|
||||
'Accept: application/json',
|
||||
'X-App-Name: widget_pvz',
|
||||
'X-App-Version: 3.11.1'
|
||||
);
|
||||
|
||||
if ($this->authToken) {
|
||||
$headers[] = "Authorization: Bearer $this->authToken";
|
||||
}
|
||||
|
||||
if ($useFormData) {
|
||||
curl_setopt_array($ch, array(
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $data,
|
||||
));
|
||||
} elseif ($useJson) {
|
||||
$headers[] = 'Content-Type: application/json';
|
||||
curl_setopt_array($ch, array(
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($data),
|
||||
));
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_URL, "$this->baseUrl/$method?" . http_build_query($data));
|
||||
}
|
||||
|
||||
curl_setopt_array($ch, array(
|
||||
CURLOPT_USERAGENT => 'widget/3.11.1',
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HEADER => true,
|
||||
));
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$headers = substr($response, 0, $headerSize);
|
||||
$result = substr($response, $headerSize);
|
||||
|
||||
$addedHeaders = $this->getHeaderValue($headers);
|
||||
|
||||
if ($result === false) {
|
||||
throw new RuntimeException(curl_error($ch), curl_errno($ch));
|
||||
}
|
||||
|
||||
return array('result' => $result, 'addedHeaders' => $addedHeaders);
|
||||
}
|
||||
|
||||
private function getHeaderValue($headers)
|
||||
{
|
||||
$headerLines = explode("\r\n", $headers);
|
||||
return array_filter($headerLines, static function ($line) {
|
||||
return !empty($line) && stripos($line, 'X-') !== false;
|
||||
});
|
||||
}
|
||||
|
||||
private function endMetrics($metricName, $metricDescription, $start)
|
||||
{
|
||||
$this->metrics[] = array(
|
||||
'name' => $metricName,
|
||||
'description' => $metricDescription,
|
||||
'time' => round(
|
||||
function_exists('hrtime') ? (hrtime(true) - $start) / 1e+6 : (microtime(true) - $start) * 1000,
|
||||
2
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function sendResponse($data, $start)
|
||||
{
|
||||
$this->http_response_code(200);
|
||||
header('Content-Type: application/json');
|
||||
header('X-Service-Version: 3.11.1');
|
||||
if (!empty($data['addedHeaders'])) {
|
||||
foreach ($data['addedHeaders'] as $header) {
|
||||
header($header);
|
||||
}
|
||||
}
|
||||
|
||||
$this->endMetrics('total', 'Total Time', $start);
|
||||
|
||||
if (!empty($this->metrics)) {
|
||||
header('Server-Timing: ' . array_reduce($this->metrics, function ($c, $i) {
|
||||
return $c . $i['name'] . ';desc="' . $i['description'] . '";dur=' . $i['time'] . ',';
|
||||
}, ''));
|
||||
}
|
||||
|
||||
echo $data['result'];
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
protected function getOffices()
|
||||
{
|
||||
$time = $this->startMetrics();
|
||||
$result = $this->httpRequest('deliverypoints', $this->requestData);
|
||||
|
||||
$this->endMetrics('office', 'Offices Request', $time);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function calculate()
|
||||
{
|
||||
$time = $this->startMetrics();
|
||||
$result = $this->httpRequest('calculator/tarifflist', $this->requestData, false, true);
|
||||
|
||||
$this->endMetrics('calc', 'Calculate Request', $time);
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -799,6 +799,15 @@ Object.assign(
|
|||
cost.innerText = json.cost;
|
||||
}
|
||||
|
||||
// Dispatching event
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("core.cart.summary.received", {
|
||||
detail: {
|
||||
json,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Exit (success)
|
||||
resolve(json);
|
||||
}
|
||||
|
|
|
@ -329,6 +329,7 @@ Object.assign(
|
|||
exit_icon.classList.add("icon", "close");
|
||||
|
||||
const images = document.createElement("div");
|
||||
images.setAttribute("id", "images");
|
||||
images.classList.add("images", "unselectable");
|
||||
|
||||
for (
|
||||
|
@ -350,7 +351,8 @@ Object.assign(
|
|||
let width = 0;
|
||||
let buffer;
|
||||
[...images.children].forEach(
|
||||
(child) => (width += child.offsetWidth +
|
||||
// 150px instead of child.offsetWidth by min-width in window.css
|
||||
(child) => (width += 150 +
|
||||
(isNaN(
|
||||
buffer = parseFloat(
|
||||
getComputedStyle(child).marginRight,
|
||||
|
@ -368,66 +370,84 @@ Object.assign(
|
|||
images.addEventListener("mousedown", _images_from);
|
||||
images.addEventListener("touchstart", _images_from);
|
||||
|
||||
let touches;
|
||||
images.addEventListener('touchmove', (move) => {
|
||||
touches = move.touches;
|
||||
});
|
||||
|
||||
const _open = (event) => {
|
||||
if (
|
||||
event.type === "touchstart" ||
|
||||
event.button === 0
|
||||
) {
|
||||
{
|
||||
const x = event.pageX || event.touches[0].pageX;
|
||||
const y = event.pageY || event.touches[0].pageY;
|
||||
const _x = images_from.pageX ||
|
||||
images_from.touches[0].pageX;
|
||||
const _y = images_from.pageY ||
|
||||
images_from.touches[0].pageY;
|
||||
const x = event.pageX ||
|
||||
(event.touches && event.touches[0]?.pageX) || 0;
|
||||
const y = event.pageY ||
|
||||
(event.touches && event.touches[0]?.pageY) || 0;
|
||||
const _x = images_from.pageX ||
|
||||
(images_from.touches &&
|
||||
images_from.touches[0]?.pageX) ||
|
||||
0;
|
||||
const _y = images_from.pageY ||
|
||||
(images_from.touches &&
|
||||
images_from.touches[0]?.pageY) ||
|
||||
0;
|
||||
|
||||
if (
|
||||
_x - x < 10 &&
|
||||
_x - x > -10 &&
|
||||
_y - y < 10 &&
|
||||
_y - y > -10
|
||||
) {
|
||||
// Replacing small images with big images
|
||||
Array.from(images.children).forEach((image) =>
|
||||
image.setAttribute(
|
||||
"src",
|
||||
image.getAttribute("data-image-big"),
|
||||
)
|
||||
);
|
||||
if (
|
||||
_x - x < 10 &&
|
||||
_x - x > -10 &&
|
||||
_y - y < 10 &&
|
||||
_y - y > -10
|
||||
) {
|
||||
// Replacing small images with big images
|
||||
Array.from(images.children).forEach((image) =>
|
||||
image.setAttribute(
|
||||
"src",
|
||||
image.getAttribute("data-image-big"),
|
||||
)
|
||||
);
|
||||
|
||||
// Expanding the "Web App" window
|
||||
core.telegram.api.expand();
|
||||
// Expanding the "Web App" window
|
||||
core.telegram.api.expand();
|
||||
core.telegram.api.disableVerticalSwipes();
|
||||
|
||||
images.classList.add("extend");
|
||||
images.classList.add("extend");
|
||||
|
||||
if (button) {
|
||||
core.telegram.api.MainButton.hide();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
images.hotline.step = 0;
|
||||
images.hotline.wheel = false;
|
||||
images.hotline.start();
|
||||
images.addEventListener("mouseup", _close);
|
||||
images.addEventListener("touchend", _close);
|
||||
}, 300);
|
||||
images.removeEventListener("mouseup", _open);
|
||||
images.removeEventListener("touchend", _open);
|
||||
if (button) {
|
||||
core.telegram.api.MainButton.hide();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
images.hotline.alive = false;
|
||||
images.hotline.movable = false;
|
||||
images.hotline.restart();
|
||||
|
||||
images.addEventListener("mouseup", _close);
|
||||
images.addEventListener("touchend", _close);
|
||||
}, 300);
|
||||
images.removeEventListener("mouseup", _open);
|
||||
images.removeEventListener("touchend", _open);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _close = (event) => {
|
||||
const x = event.pageX || event.touches[0].pageX;
|
||||
const y = event.pageY || event.touches[0].pageY;
|
||||
console.log(event)
|
||||
const x = event.pageX ||
|
||||
(touches && touches[0]?.pageX) || 0;
|
||||
const y = event.pageY ||
|
||||
(touches && touches[0]?.pageY) || 0;
|
||||
const _x = images_from.pageX ||
|
||||
images_from.touches[0].pageX;
|
||||
(images_from.touches &&
|
||||
images_from.touches[0]?.pageX) ||
|
||||
0;
|
||||
const _y = images_from.pageY ||
|
||||
images_from.touches[0].pageY;
|
||||
(images_from.touches &&
|
||||
images_from.touches[0]?.pageY) ||
|
||||
0;
|
||||
|
||||
if (
|
||||
event.type === "touchstart" ||
|
||||
event.type === "touchend" ||
|
||||
event.button === 0
|
||||
) {
|
||||
if (
|
||||
|
@ -440,8 +460,11 @@ Object.assign(
|
|||
// (в идеале надо переделать на таймер 2 секунды есди зажата кнопка то ничего не делать а просто двигать)
|
||||
// пох абсолютно сейчас заказчик слишком охуевший для этого
|
||||
|
||||
images.hotline.step = -0.3;
|
||||
images.hotline.movable = true;
|
||||
images.hotline.alive = true;
|
||||
images.hotline.step = -1;
|
||||
images.hotline.wheel = true;
|
||||
images.hotline.restart();
|
||||
|
||||
if (width < card.offsetWidth) {
|
||||
images.hotline.stop();
|
||||
|
@ -457,6 +480,9 @@ Object.assign(
|
|||
|
||||
images.classList.remove("extend");
|
||||
|
||||
|
||||
core.telegram.api.enableVerticalSwipes();
|
||||
|
||||
if (button) {
|
||||
core.telegram.api.MainButton.show();
|
||||
}
|
||||
|
@ -465,10 +491,30 @@ Object.assign(
|
|||
images.removeEventListener("touchend", _close);
|
||||
images.addEventListener("mousedown", _start);
|
||||
images.addEventListener("touchstart", _start);
|
||||
} else {
|
||||
// Курсор был сдвинут более чем на 10 пикселей
|
||||
|
||||
if (x > _x) images.hotline.forward();
|
||||
else images.hotline.backward();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _start = (event) => {
|
||||
if (
|
||||
event.type === "touchstart" ||
|
||||
event.button === 0
|
||||
) {
|
||||
images.removeEventListener("mousedown", _start);
|
||||
images.removeEventListener("touchstart", _start);
|
||||
images.addEventListener("mouseup", _open);
|
||||
images.addEventListener("touchend", _open);
|
||||
}
|
||||
};
|
||||
|
||||
images.addEventListener("mousedown", _start);
|
||||
images.addEventListener("touchstart", _start);
|
||||
|
||||
const header = document.createElement("p");
|
||||
header.classList.add("header");
|
||||
|
||||
|
@ -610,7 +656,6 @@ Object.assign(
|
|||
wrap.addEventListener("touchstart", _from);
|
||||
|
||||
const remove = (event) => {
|
||||
console.log("BABLO: " + typeof event);
|
||||
if (
|
||||
typeof event === "undefined" ||
|
||||
event.type !== "popstate"
|
||||
|
@ -625,8 +670,6 @@ Object.assign(
|
|||
if (parameters.get("product") === identifier) {
|
||||
// The previous window with the product card was exactly the same
|
||||
|
||||
console.log("aboba");
|
||||
|
||||
// Deleting product card
|
||||
parameters.delete("product");
|
||||
|
||||
|
@ -698,38 +741,26 @@ Object.assign(
|
|||
core.telegram.api.BackButton.show();
|
||||
core.telegram.api.BackButton.onClick(remove);
|
||||
|
||||
setTimeout(() => {
|
||||
import("./hotline.js").then((hotline) => {
|
||||
// Imported the hotline module
|
||||
// setTimeout(() => {
|
||||
import("./hotline.mjs").then((hotline) => {
|
||||
// Imported the hotline module
|
||||
images.hotline = new hotline.default(
|
||||
images,
|
||||
);
|
||||
images.hotline.step = -1;
|
||||
images.hotline.interval = 20;
|
||||
images.hotline.wheel = true;
|
||||
images.hotline.touch = true;
|
||||
images.hotline.events.set("transfer.beginning", true);
|
||||
images.hotline.events.set("transfer.end", true);
|
||||
images.hotline.events.set("moved.forward", true);
|
||||
images.hotline.events.set("moved.backward", true);
|
||||
|
||||
const _start = (event) => {
|
||||
if (
|
||||
event.type === "touchstart" ||
|
||||
event.button === 0
|
||||
) {
|
||||
images.removeEventListener("mousedown", _start);
|
||||
images.removeEventListener("touchstart", _start);
|
||||
images.addEventListener("mouseup", _open);
|
||||
images.addEventListener("touchend", _open);
|
||||
}
|
||||
};
|
||||
|
||||
images.addEventListener("mousedown", _start);
|
||||
images.addEventListener("touchstart", _start);
|
||||
|
||||
images.hotline = new hotline.default(
|
||||
json.product.identfier,
|
||||
images,
|
||||
);
|
||||
images.hotline.step = -0.3;
|
||||
images.hotline.wheel = true;
|
||||
images.hotline.touch = true;
|
||||
|
||||
if (width > card.offsetWidth) {
|
||||
images.hotline.start();
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
if (width > card.offsetWidth) {
|
||||
images.hotline.start();
|
||||
}
|
||||
});
|
||||
// }, 300);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ export default function damper(func, timeout = 300, force) {
|
|||
// Requested execution with ignoring the timer
|
||||
|
||||
// Deleting the force argument
|
||||
if (typeof force === "number") delete args[force - 1];
|
||||
if (typeof force === "number") args.splice(force - 1, force);
|
||||
|
||||
// Writing promise handlers into the arguments variable
|
||||
args.push(resolve, reject);
|
||||
|
|
|
@ -93,7 +93,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.add("deleted");
|
||||
request.classList.add("hidden");
|
||||
}
|
||||
} else {
|
||||
// Not received readiness status or readiness status is false
|
||||
|
@ -102,7 +102,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.remove("deleted");
|
||||
request.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,100 @@ export default class delivery {
|
|||
button.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (json.delivery) {
|
||||
// Received delivery HTML-code
|
||||
|
||||
core.modules.connect(["telegram"])
|
||||
.then(() => {
|
||||
//
|
||||
|
||||
core.telegram.api.LocationManager.init(() => {
|
||||
//if (core.telegram.api.LocationManager.isAccessRequested && !core.telegram.api.LocationManager.isAccessGranted) {
|
||||
// alert('Предоставьте разрешение на доступ к геопозиции');
|
||||
// core.telegram.api.LocationManager.openSettings();
|
||||
//}
|
||||
|
||||
if (!core.telegram.api.LocationManager.isLocationAvailable) {
|
||||
// Dispatching event
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("core.telegram.api.location.rejected"),
|
||||
);
|
||||
} else {
|
||||
core.telegram.api.LocationManager.getLocation(
|
||||
(location) => {
|
||||
// Dispatching event
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(
|
||||
"core.telegram.api.location.received",
|
||||
{
|
||||
detail: {
|
||||
location,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initializing the deliveries <div> element
|
||||
const deliveries = document.getElementById("deliveries");
|
||||
|
||||
if (deliveries instanceof HTMLElement) {
|
||||
// Initialized the deliveries <div> element
|
||||
|
||||
// Initializing the deliveries <section> element
|
||||
let section = deliveries.nextElementSibling;
|
||||
|
||||
if (section instanceof HTMLElement) {
|
||||
// Initialized the deliveries <section> element
|
||||
|
||||
// Deinitializing the delivery <section> element
|
||||
section.remove();
|
||||
}
|
||||
|
||||
// Creating the delivery <section> element
|
||||
section = document.createElement("section");
|
||||
|
||||
// Writing the delivery <section> element after the delivery <div> element
|
||||
deliveries.parentElement.insertBefore(
|
||||
section,
|
||||
deliveries.nextElementSibling,
|
||||
);
|
||||
|
||||
// Reinitializing the delivery <section> element
|
||||
section.outerHTML = json.delivery.html;
|
||||
|
||||
// Reinitializing the deliveries <section> element
|
||||
section = deliveries.nextElementSibling;
|
||||
|
||||
for (const javascript of json.delivery.javascript) {
|
||||
// Received delivery JavaScript-code and delivery JavaScript-links
|
||||
|
||||
// Initializing the delivery JavaScript-code <script> element
|
||||
const script = document.createElement("script");
|
||||
script.setAttribute("defer", "true");
|
||||
|
||||
if (javascript.link) {
|
||||
// Initializing the delivery JavaScript-link <script> element attributes
|
||||
script.setAttribute("type", "text/javascript");
|
||||
script.setAttribute("src", javascript.link);
|
||||
script.setAttribute("charset", 'charset="utf-8');
|
||||
} else if (javascript.code) {
|
||||
// Delivery JavaScript-code
|
||||
|
||||
// Initializing the delivery JavaScript-code <script> element value
|
||||
script.innerHTML = javascript.code;
|
||||
}
|
||||
|
||||
// Writing the delivery JavaScript-code <script> element and executing the delivery JavaScript-code
|
||||
section.appendChild(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -241,7 +335,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.add("deleted");
|
||||
request.classList.add("hidden");
|
||||
}
|
||||
} else {
|
||||
// Not received readiness status or readiness status is false
|
||||
|
@ -250,7 +344,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.remove("deleted");
|
||||
request.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,7 +562,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.add("deleted");
|
||||
request.classList.add("hidden");
|
||||
}
|
||||
|
||||
core.modules.connect("telegram").then(() => {
|
||||
|
@ -483,7 +577,7 @@ export default class delivery {
|
|||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.remove("deleted");
|
||||
request.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,6 +1031,15 @@ Object.assign(
|
|||
document.getElementById("shipping")?.remove();
|
||||
}
|
||||
|
||||
// Dispatching event
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("core.delivery.calculated", {
|
||||
detail: {
|
||||
json,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Exit (success)
|
||||
resolve(json);
|
||||
}
|
||||
|
|
|
@ -1,750 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @name Бегущая строка
|
||||
*
|
||||
* @description
|
||||
* Простой, но мощный класс для создания бегущих строк. Поддерживает
|
||||
* перемещение мышью и прокрутку колесом, полностью настраивается очень гибок
|
||||
* для настроек в CSS и подразумевается, что отлично индексируется поисковыми роботами.
|
||||
* Имеет свой препроцессор, благодаря которому можно создавать бегущие строки
|
||||
* без программирования - с помощью HTML-аттрибутов, а так же возможность
|
||||
* изменять параметры (data-hotline-* аттрибуты) на лету. Есть возможность вызывать
|
||||
* события при выбранных действиях для того, чтобы пользователь имел возможность
|
||||
* дорабатывать функционал без изучения и изменения моего кода
|
||||
*
|
||||
* @example
|
||||
* сonst hotline = new hotline();
|
||||
* hotline.step = '-5';
|
||||
* hotline.start();
|
||||
*
|
||||
* @todo
|
||||
* 1. Бесконечный режим - элементы не удаляются если видны на экране (будут дубликаты).
|
||||
* Сейчас при БЫСТРОМ прокручивании можно заметит как элементы "появляются" в начале и конце строки.
|
||||
* 2. "gap" and "padding" in wrap should be removed! or added here to the calculations
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
export default class hotline {
|
||||
// Идентификатор
|
||||
#id = 0;
|
||||
|
||||
// Оболочка (instanceof HTMLElement)
|
||||
#shell = document.getElementById("hotline");
|
||||
|
||||
// Инстанция горячей строки
|
||||
#instance = null;
|
||||
|
||||
// Перемещение
|
||||
#transfer = true;
|
||||
|
||||
// Движение
|
||||
#move = true;
|
||||
|
||||
// Наблюдатель
|
||||
#observer = null;
|
||||
|
||||
// Реестр запрещённых к изменению параметров
|
||||
#block = new Set(["events"]);
|
||||
|
||||
// Status (null, active, inactive)
|
||||
#status = null;
|
||||
|
||||
// Настраиваемые параметры
|
||||
transfer = null;
|
||||
move = null;
|
||||
delay = 10;
|
||||
step = 1;
|
||||
hover = true;
|
||||
movable = true;
|
||||
sticky = false;
|
||||
wheel = false;
|
||||
delta = null;
|
||||
vertical = false;
|
||||
button = 0; // button for grabbing. 0 is main mouse button (left)
|
||||
observe = false;
|
||||
events = new Map([
|
||||
["start", false],
|
||||
["stop", false],
|
||||
["move", false],
|
||||
["move.block", false],
|
||||
["move.unblock", false],
|
||||
["offset", false],
|
||||
["transfer.start", true],
|
||||
["transfer.end", true],
|
||||
["mousemove", false],
|
||||
["touchmove", false],
|
||||
]);
|
||||
|
||||
// Is hotline currently moving due to "onmousemove" or "ontouchmove"?
|
||||
moving = false;
|
||||
|
||||
constructor(id, shell) {
|
||||
// Запись идентификатора
|
||||
if (typeof id === "string" || typeof id === "number") this.#id = id;
|
||||
|
||||
// Запись оболочки
|
||||
if (shell instanceof HTMLElement) this.#shell = shell;
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.#instance === null) {
|
||||
// Нет запущенной инстанции бегущей строки
|
||||
|
||||
// Инициализация ссылки на ядро
|
||||
const _this = this;
|
||||
|
||||
// Запуск движения
|
||||
this.#instance = setInterval(function () {
|
||||
if (_this.#shell.childElementCount > 1) {
|
||||
// Найдено содержимое бегущей строки (2 и более)
|
||||
|
||||
// Инициализация буфера для временных данных
|
||||
let buffer;
|
||||
|
||||
// Инициализация данных первого элемента в строке
|
||||
const first = {
|
||||
element: (buffer = _this.#shell.firstElementChild),
|
||||
coords: buffer.getBoundingClientRect(),
|
||||
};
|
||||
|
||||
if (_this.vertical) {
|
||||
// Вертикальная бегущая строка
|
||||
|
||||
// Инициализация сдвига у первого элемента (движение)
|
||||
first.offset = isNaN(
|
||||
buffer = parseFloat(first.element.style.marginTop),
|
||||
)
|
||||
? 0
|
||||
: buffer;
|
||||
|
||||
// Инициализация отступа до второго элемента у первого элемента (разделение)
|
||||
first.separator = isNaN(
|
||||
buffer = parseFloat(
|
||||
getComputedStyle(first.element).marginBottom,
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer;
|
||||
|
||||
// Инициализация крайнего с конца ребра первого элемента в строке
|
||||
first.end = first.coords.y + first.coords.height +
|
||||
first.separator;
|
||||
} else {
|
||||
// Горизонтальная бегущая строка
|
||||
|
||||
// Инициализация отступа у первого элемента (движение)
|
||||
first.offset = isNaN(
|
||||
buffer = parseFloat(first.element.style.marginLeft),
|
||||
)
|
||||
? 0
|
||||
: buffer;
|
||||
|
||||
// Инициализация отступа до второго элемента у первого элемента (разделение)
|
||||
first.separator = isNaN(
|
||||
buffer = parseFloat(
|
||||
getComputedStyle(first.element).marginRight,
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer;
|
||||
|
||||
// Инициализация крайнего с конца ребра первого элемента в строке
|
||||
first.end = first.coords.x + first.coords.width +
|
||||
first.separator;
|
||||
}
|
||||
|
||||
if (
|
||||
(_this.vertical &&
|
||||
Math.round(first.end) < _this.#shell.offsetTop) ||
|
||||
(!_this.vertical &&
|
||||
Math.round(first.end) < _this.#shell.offsetLeft)
|
||||
) {
|
||||
// Элемент (вместе с отступом до второго элемента) вышел из области видимости (строки)
|
||||
|
||||
if (
|
||||
(_this.transfer === null && _this.#transfer) ||
|
||||
_this.transfer === true
|
||||
) {
|
||||
// Перенос разрешен
|
||||
|
||||
if (_this.vertical) {
|
||||
// Вертикальная бегущая строка
|
||||
|
||||
// Удаление отступов (движения)
|
||||
first.element.style.marginTop = null;
|
||||
} else {
|
||||
// Горизонтальная бегущая строка
|
||||
|
||||
// Удаление отступов (движения)
|
||||
first.element.style.marginLeft = null;
|
||||
}
|
||||
|
||||
// Копирование первого элемента в конец строки
|
||||
_this.#shell.appendChild(first.element);
|
||||
|
||||
if (_this.events.get("transfer.end")) {
|
||||
// Запрошен вызов события: "перемещение в конец"
|
||||
|
||||
// Вызов события: "перемещение в конец"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.transfer.end`, {
|
||||
detail: {
|
||||
element: first.element,
|
||||
offset: -(
|
||||
(_this.vertical
|
||||
? first.coords.height
|
||||
: first.coords.width) + first.separator
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
(_this.vertical &&
|
||||
Math.round(first.coords.y) > _this.#shell.offsetTop) ||
|
||||
(!_this.vertical &&
|
||||
Math.round(first.coords.x) > _this.#shell.offsetLeft)
|
||||
) {
|
||||
// Передняя (движущая) граница первого элемента вышла из области видимости
|
||||
|
||||
if (
|
||||
(_this.transfer === null && _this.#transfer) ||
|
||||
_this.transfer === true
|
||||
) {
|
||||
// Перенос разрешен
|
||||
|
||||
// Инициализация отступа у последнего элемента (разделение)
|
||||
const separator = (buffer = isNaN(
|
||||
buffer = parseFloat(
|
||||
getComputedStyle(_this.#shell.lastElementChild)[
|
||||
_this.vertical ? "marginBottom" : "marginRight"
|
||||
],
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer) === 0
|
||||
? first.separator
|
||||
: buffer;
|
||||
|
||||
// Инициализация координат первого элемента в строке
|
||||
const coords = _this.#shell.lastElementChild
|
||||
.getBoundingClientRect();
|
||||
|
||||
if (_this.vertical) {
|
||||
// Вертикальная бегущая строка
|
||||
|
||||
// Удаление отступов (движения)
|
||||
_this.#shell.lastElementChild.style.marginTop = -coords.height -
|
||||
separator + "px";
|
||||
} else {
|
||||
// Горизонтальная бегущая строка
|
||||
|
||||
// Удаление отступов (движения)
|
||||
_this.#shell.lastElementChild.style.marginLeft = -coords.width -
|
||||
separator + "px";
|
||||
}
|
||||
|
||||
// Копирование последнего элемента в начало строки
|
||||
_this.#shell.insertBefore(
|
||||
_this.#shell.lastElementChild,
|
||||
first.element,
|
||||
);
|
||||
|
||||
// Удаление отступов у второго элемента в строке (движения)
|
||||
_this.#shell.children[1].style[
|
||||
_this.vertical ? "marginTop" : "marginLeft"
|
||||
] = null;
|
||||
|
||||
if (_this.events.get("transfer.start")) {
|
||||
// Запрошен вызов события: "перемещение в начало"
|
||||
|
||||
// Вызов события: "перемещение в начало"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.transfer.start`, {
|
||||
detail: {
|
||||
element: _this.#shell.lastElementChild,
|
||||
offset: (_this.vertical ? coords.height : coords.width) +
|
||||
separator,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Элемент в области видимости
|
||||
|
||||
if (
|
||||
(_this.move === null && _this.#move) || _this.move === true
|
||||
) {
|
||||
// Движение разрешено
|
||||
|
||||
// Запись новых координат сдвига
|
||||
const offset = first.offset + _this.step;
|
||||
|
||||
// Запись сдвига (движение)
|
||||
_this.offset(offset);
|
||||
|
||||
if (_this.events.get("move")) {
|
||||
// Запрошен вызов события: "движение"
|
||||
|
||||
// Вызов события: "движение"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.move`, {
|
||||
detail: {
|
||||
from: first.offset,
|
||||
to: offset,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, _this.delay);
|
||||
|
||||
if (this.hover) {
|
||||
// Запрошена возможность останавливать бегущую строку
|
||||
|
||||
// Инициализация сдвига
|
||||
let offset = 0;
|
||||
|
||||
// Инициализация слушателя события при перемещении элемента в бегущей строке
|
||||
const listener = function (e) {
|
||||
// Увеличение сдвига
|
||||
offset += e.detail.offset ?? 0;
|
||||
};
|
||||
|
||||
// Объявление переменной в области видимости обработки остановки бегущей строки
|
||||
let move;
|
||||
|
||||
// Инициализация обработчика наведения курсора (остановка движения)
|
||||
this.#shell.onmouseover = function (e) {
|
||||
// Курсор наведён на бегущую строку
|
||||
|
||||
// Блокировка движения
|
||||
_this.#move = false;
|
||||
|
||||
if (_this.events.get("move.block")) {
|
||||
// Запрошен вызов события: "блокировка движения"
|
||||
|
||||
// Вызов события: "блокировка движения"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.move.block`),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.movable) {
|
||||
// Запрошена возможность двигать бегущую строку
|
||||
|
||||
_this.#shell.onmousedown =
|
||||
_this.#shell.ontouchstart =
|
||||
function (
|
||||
start,
|
||||
) {
|
||||
// Handling a "mousedown" and a "touchstart" on hotline
|
||||
|
||||
if (
|
||||
start.type === "touchstart" ||
|
||||
start.button === _this.button
|
||||
) {
|
||||
const x = start.pageX || start.touches[0].pageX;
|
||||
const y = start.pageY || start.touches[0].pageY;
|
||||
|
||||
// Блокировка движения
|
||||
_this.#move = false;
|
||||
|
||||
if (_this.events.get("move.block")) {
|
||||
// Запрошен вызов события: "блокировка движения"
|
||||
|
||||
// Вызов события: "блокировка движения"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.move.block`),
|
||||
);
|
||||
}
|
||||
|
||||
// Инициализация слушателей события перемещения элемента в бегущей строке
|
||||
document.addEventListener(
|
||||
`hotline.${_this.#id}.transfer.start`,
|
||||
listener,
|
||||
);
|
||||
document.addEventListener(
|
||||
`hotline.${_this.#id}.transfer.end`,
|
||||
listener,
|
||||
);
|
||||
|
||||
// Инициализация буфера для временных данных
|
||||
let buffer;
|
||||
|
||||
// Инициализация данных первого элемента в строке
|
||||
const first = {
|
||||
offset: isNaN(
|
||||
buffer = parseFloat(
|
||||
_this.vertical
|
||||
? _this.#shell.firstElementChild.style
|
||||
.marginTop
|
||||
: _this.#shell.firstElementChild.style
|
||||
.marginLeft,
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer,
|
||||
};
|
||||
|
||||
move = (move) => {
|
||||
// Обработка движения курсора
|
||||
|
||||
if (_this.#status === "active") {
|
||||
// Запись статуса ручного перемещения
|
||||
_this.moving = true;
|
||||
|
||||
const _x = move.pageX || move.touches[0].pageX;
|
||||
const _y = move.pageY || move.touches[0].pageY;
|
||||
|
||||
if (_this.vertical) {
|
||||
// Вертикальная бегущая строка
|
||||
|
||||
// Инициализация буфера местоположения
|
||||
const from =
|
||||
_this.#shell.firstElementChild.style.marginTop;
|
||||
const to = _y - (y + offset - first.offset);
|
||||
|
||||
// Движение
|
||||
_this.#shell.firstElementChild.style.marginTop = to +
|
||||
"px";
|
||||
} else {
|
||||
// Горизонтальная бегущая строка
|
||||
|
||||
// Инициализация буфера местоположения
|
||||
const from =
|
||||
_this.#shell.firstElementChild.style.marginLeft;
|
||||
const to = _x - (x + offset - first.offset);
|
||||
|
||||
// Движение
|
||||
_this.#shell.firstElementChild.style.marginLeft = to +
|
||||
"px";
|
||||
}
|
||||
|
||||
if (_this.events.get(move.type)) {
|
||||
// Запрошен вызов события: "перемещение" (мышью или касанием)
|
||||
|
||||
// Вызов события: "перемещение" (мышью или касанием)
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(
|
||||
`hotline.${_this.#id}.${move.type}`,
|
||||
{
|
||||
detail: { from, to },
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Запись курсора
|
||||
_this.#shell.style.cursor = "grabbing";
|
||||
}
|
||||
};
|
||||
|
||||
// Запуск обработки движения
|
||||
document.addEventListener("mousemove", move);
|
||||
document.addEventListener("touchmove", move);
|
||||
}
|
||||
};
|
||||
|
||||
// Перещапись событий браузера (чтобы не дёргалось)
|
||||
_this.#shell.ondragstart = null;
|
||||
|
||||
_this.#shell.onmouseup = _this.#shell.ontouchend = function () {
|
||||
// Курсор деактивирован
|
||||
|
||||
// Запись статуса ручного перемещения
|
||||
_this.moving = false;
|
||||
|
||||
// Остановка обработки движения
|
||||
document.removeEventListener("mousemove", move);
|
||||
document.removeEventListener("touchmove", move);
|
||||
|
||||
// Сброс сдвига
|
||||
offset = 0;
|
||||
|
||||
document.removeEventListener(
|
||||
`hotline.${_this.#id}.transfer.start`,
|
||||
listener,
|
||||
);
|
||||
document.removeEventListener(
|
||||
`hotline.${_this.#id}.transfer.end`,
|
||||
listener,
|
||||
);
|
||||
|
||||
// Разблокировка движения
|
||||
_this.#move = true;
|
||||
|
||||
if (_this.events.get("move.unblock")) {
|
||||
// Запрошен вызов события: "разблокировка движения"
|
||||
|
||||
// Вызов события: "разблокировка движения"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.move.unblock`),
|
||||
);
|
||||
}
|
||||
|
||||
// Восстановление курсора
|
||||
_this.#shell.style.cursor = null;
|
||||
};
|
||||
}
|
||||
|
||||
// Инициализация обработчика отведения курсора (остановка движения)
|
||||
this.#shell.onmouseleave = function (onmouseleave) {
|
||||
// Курсор отведён от бегущей строки
|
||||
|
||||
if (!_this.sticky) {
|
||||
// Отключено прилипание
|
||||
|
||||
// Запись статуса ручного перемещения
|
||||
_this.moving = false;
|
||||
|
||||
// Остановка обработки движения
|
||||
document.removeEventListener("mousemove", move);
|
||||
document.removeEventListener("touchmove", move);
|
||||
|
||||
document.removeEventListener(
|
||||
`hotline.${_this.#id}.transfer.start`,
|
||||
listener,
|
||||
);
|
||||
document.removeEventListener(
|
||||
`hotline.${_this.#id}.transfer.end`,
|
||||
listener,
|
||||
);
|
||||
|
||||
// Восстановление курсора
|
||||
_this.#shell.style.cursor = null;
|
||||
}
|
||||
|
||||
// Сброс сдвига
|
||||
offset = 0;
|
||||
|
||||
// Разблокировка движения
|
||||
_this.#move = true;
|
||||
|
||||
if (_this.events.get("move.unblock")) {
|
||||
// Запрошен вызов события: "разблокировка движения"
|
||||
|
||||
// Вызов события: "разблокировка движения"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${_this.#id}.move.unblock`),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (this.wheel) {
|
||||
// Запрошена возможность прокручивать колесом мыши
|
||||
|
||||
// Инициализация обработчика наведения курсора (остановка движения)
|
||||
this.#shell.onwheel = function (e) {
|
||||
// Курсор наведён на бегущую
|
||||
|
||||
// Инициализация буфера для временных данных
|
||||
let buffer;
|
||||
|
||||
// Перемещение
|
||||
_this.offset(
|
||||
(isNaN(
|
||||
buffer = parseFloat(
|
||||
_this.#shell.firstElementChild.style[
|
||||
_this.vertical ? "marginTop" : "marginLeft"
|
||||
],
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer) +
|
||||
(_this.delta === null
|
||||
? e.wheelDelta
|
||||
: e.wheelDelta > 0
|
||||
? _this.delta
|
||||
: -_this.delta),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
this.#status = "active";
|
||||
}
|
||||
|
||||
if (this.observe) {
|
||||
// Запрошено наблюдение за изменениями аттрибутов элемента бегущей строки
|
||||
|
||||
if (this.#observer === null) {
|
||||
// Отсутствует наблюдатель
|
||||
|
||||
// Инициализация ссылки на ядро
|
||||
const _this = this;
|
||||
|
||||
// Инициализация наблюдателя
|
||||
this.#observer = new MutationObserver(function (mutations) {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === "attributes") {
|
||||
// Запись параметра в инстанцию бегущей строки
|
||||
_this.configure(mutation.attributeName);
|
||||
}
|
||||
}
|
||||
|
||||
// Перезапуск бегущей строки
|
||||
_this.restart();
|
||||
});
|
||||
|
||||
// Активация наблюдения
|
||||
this.#observer.observe(this.#shell, {
|
||||
attributes: true,
|
||||
});
|
||||
}
|
||||
} else if (this.#observer instanceof MutationObserver) {
|
||||
// Запрошено отключение наблюдения
|
||||
|
||||
// Деактивация наблюдения
|
||||
this.#observer.disconnect();
|
||||
|
||||
// Удаление наблюдателя
|
||||
this.#observer = null;
|
||||
}
|
||||
|
||||
if (this.events.get("start")) {
|
||||
// Запрошен вызов события: "запуск"
|
||||
|
||||
// Вызов события: "запуск"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${this.#id}.start`),
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.#status = "inactive";
|
||||
|
||||
// Остановка бегущей строки
|
||||
clearInterval(this.#instance);
|
||||
|
||||
// Удаление инстанции интервала
|
||||
this.#instance = null;
|
||||
|
||||
if (this.events.get("stop")) {
|
||||
// Запрошен вызов события: "остановка"
|
||||
|
||||
// Вызов события: "остановка"
|
||||
document.dispatchEvent(new CustomEvent(`hotline.${this.#id}.stop`));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
restart() {
|
||||
// Остановка бегущей строки
|
||||
this.stop();
|
||||
|
||||
// Запуск бегущей строки
|
||||
this.start();
|
||||
}
|
||||
|
||||
configure(attribute) {
|
||||
// Инициализация названия параметра
|
||||
const parameter = (/^data-hotline-(\w+)$/.exec(attribute) ?? [, null])[1];
|
||||
|
||||
if (typeof parameter === "string") {
|
||||
// Параметр найден
|
||||
|
||||
// Проверка на разрешение изменения
|
||||
if (this.#block.has(parameter)) return;
|
||||
|
||||
// Инициализация значения параметра
|
||||
const value = this.#shell.getAttribute(attribute);
|
||||
|
||||
if (typeof value !== undefined || typeof value !== null) {
|
||||
// Найдено значение
|
||||
|
||||
// Инициализация буфера для временных данных
|
||||
let buffer;
|
||||
|
||||
// Запись параметра
|
||||
this[parameter] = isNaN(buffer = parseFloat(value))
|
||||
? value === "true" ? true : value === "false" ? false : value
|
||||
: buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
offset(value) {
|
||||
// Запись отступа
|
||||
this.#shell.firstElementChild.style[
|
||||
this.vertical ? "marginTop" : "marginLeft"
|
||||
] = value + "px";
|
||||
|
||||
if (this.events.get("offset")) {
|
||||
// Запрошен вызов события: "сдвиг"
|
||||
|
||||
// Вызов события: "сдвиг"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.${this.#id}.offset`, {
|
||||
detail: {
|
||||
to: value,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static preprocessing(event = false) {
|
||||
// Инициализация счётчиков инстанций горячей строки
|
||||
const success = new Set();
|
||||
let error = 0;
|
||||
|
||||
for (
|
||||
const element of document.querySelectorAll('*[data-hotline="true"]')
|
||||
) {
|
||||
// Перебор элементов для инициализации бегущих строк
|
||||
|
||||
if (typeof element.id === "string") {
|
||||
// Найден идентификатор
|
||||
|
||||
// Инициализация инстанции бегущей строки
|
||||
const hotline = new this(element.id, element);
|
||||
|
||||
for (const attribute of element.getAttributeNames()) {
|
||||
// Перебор аттрибутов
|
||||
|
||||
// Запись параметра в инстанцию бегущей строки
|
||||
hotline.configure(attribute);
|
||||
}
|
||||
|
||||
// Запуск бегущей строки
|
||||
hotline.start();
|
||||
|
||||
// Запись инстанции бегущей строки в элемент
|
||||
element.hotline = hotline;
|
||||
|
||||
// Запись в счётчик успешных инициализаций
|
||||
success.add(hotline);
|
||||
} else ++error;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
// Запрошен вызов события: "предварительная подготовка"
|
||||
|
||||
// Вызов события: "предварительная подготовка"
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`hotline.preprocessed`, {
|
||||
detail: {
|
||||
success,
|
||||
error,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -146,4 +146,4 @@ Object.assign(
|
|||
);
|
||||
|
||||
// Connecting to the core
|
||||
if (!core.session) core.session = session;
|
||||
// if (!core.session) core.session = session;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
main>button#order,
|
||||
main>section:is(#summary, #products, #delivery, #delivery_request) {
|
||||
width: var(--width);
|
||||
gap: var(--gap);
|
||||
|
@ -48,33 +49,108 @@ main>section#delivery>div.column>div#deliveries>input:checked+label:active {
|
|||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>div#address {
|
||||
main>section#delivery>div.column>section {
|
||||
gap: 0.7rem;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#address {
|
||||
flex-flow: row wrap;
|
||||
gap: 0.7rem;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>div#address>input#location {
|
||||
main>section#delivery>div.column>section.cdek>div#address>input#location {
|
||||
min-width: max(6rem, 20%);
|
||||
width: min(6rem, 100%);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>div#address>input#street {
|
||||
main>section#delivery>div.column>section.cdek>div#address>input#street {
|
||||
min-width: max(10rem, 30%);
|
||||
width: min(10rem, 100%);
|
||||
flex-grow: 10;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column:not(:has(div#deliveries>input:checked))>div#address {
|
||||
display: none;
|
||||
main>section#delivery>div.column>section.cdek>div#map {
|
||||
height: 203px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map * {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map:not(.office, .door)>div>div:first-child,
|
||||
main>section#delivery>div.column>section.cdek>div#map>div>div:last-child a[href="https://cdek.ru"],
|
||||
main>section#delivery>div.column>section.cdek>div#map>div>div:last-child>div:first-child>div>ymaps>ymaps:last-of-type {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map:not(.office, .door)>div>div:last-child>div:first-child>div>ymaps>ymaps:is(:nth-of-type(2), :nth-of-type(4)),
|
||||
main>section#delivery>div.column>section.cdek>div#map:is(.office, .door)>div>div:last-child>div:first-child>div>ymaps>ymaps:is(:nth-of-type(1), :nth-of-type(3)) {
|
||||
margin-bottom: unset !important;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:first-child {
|
||||
order: 2;
|
||||
margin-bottom: unset !important;
|
||||
display: flex !important;
|
||||
padding: unset !important;
|
||||
flex-flow: row wrap;
|
||||
gap: 0.7rem !important;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:first-child> :is(div, div:is(:hover, :focus, :active)) {
|
||||
margin: unset !important;
|
||||
min-width: calc(50% - 0.7rem);
|
||||
padding: 0.2rem 1rem;
|
||||
flex-grow: 1;
|
||||
border-radius: 0.75rem !important;
|
||||
background-color: var(--tg-theme-button-color) !important;
|
||||
filter: unset;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:first-child>div:is(:hover, :focus) {
|
||||
filter: brightness(1.5);
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:first-child>div:active {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:first-child label {
|
||||
color: var(--tg-theme-text-color);
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map>div>div:last-child {
|
||||
border: unset !important;
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map:not(.office, .door)>div>div:last-child {
|
||||
height: 100% !important
|
||||
}
|
||||
|
||||
main>section#delivery>div.column>section.cdek>div#map.office.door>div>div:last-child {
|
||||
order: 1;
|
||||
height: calc(100% - 3.375rem - 0.5rem) !important;
|
||||
border-radius: 0.75rem !important;
|
||||
}
|
||||
|
||||
/* main>section#delivery>div.column:not(:has(div#deliveries>input:checked))>div#address {
|
||||
display: none;
|
||||
} */
|
||||
|
||||
main:has(section#summary.disabled:hover)>section#delivery>div {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
section#delivery>div.column>div#deliveries>input:not(:checked)+section#delivery_request {
|
||||
display: inline-flex;
|
||||
section#delivery.hidden+#delivery_request {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main>section#delivery_request>p:only-of-type {
|
||||
|
@ -98,11 +174,17 @@ main>section#delivery_request>p:only-of-type>span:only-of-type {
|
|||
color: var(--tg-theme-hint-color);
|
||||
}
|
||||
|
||||
main>section#summary {
|
||||
margin-top: -0.8rem;
|
||||
margin-bottom: -0.5rem;
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
main>section#summary>div {
|
||||
container-type: inline-size;
|
||||
container-name: summary;
|
||||
height: 2rem;
|
||||
padding-left: 1rem;
|
||||
padding: 0 1rem;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
overflow: hidden;
|
||||
|
@ -118,29 +200,8 @@ main>section#summary>div>span:first-of-type {
|
|||
/* margin-left: auto; */
|
||||
}
|
||||
|
||||
main>section#summary>div>button#order {
|
||||
/* margin-left: 0.3rem; */
|
||||
margin-left: auto;
|
||||
padding-left: 0.7rem;
|
||||
background: unset;
|
||||
}
|
||||
|
||||
main>section#summary>div>button#order * {
|
||||
color: var(--tg-theme-button-color);
|
||||
}
|
||||
|
||||
main>section#summary.disabled,
|
||||
main>section#summary>div:has(button#order:disabled),
|
||||
main:not(:has(section#delivery>div.column>div#deliveries>input:checked))>section#summary>div:has(button#order:enabled) {
|
||||
/* cursor: not-allowed; */
|
||||
}
|
||||
|
||||
main>section#summary.disabled,
|
||||
main>section#summary>div>button#order:disabled,
|
||||
main:not(:has(section#delivery>div.column>div#deliveries>input:checked))>section#summary>div>button#order:enabled {
|
||||
/* pointer-events: none;
|
||||
filter: grayscale(1); */
|
||||
display: none;
|
||||
main>button#order {
|
||||
/* margin-left: auto; */
|
||||
}
|
||||
|
||||
main>section#products>article.product {
|
||||
|
@ -256,6 +317,7 @@ main>section#products>article.product>div>div.footer>input {
|
|||
width: 2rem;
|
||||
padding: 0 0.3rem;
|
||||
text-align: center;
|
||||
color: var(--tg-theme-text-color);
|
||||
}
|
||||
|
||||
@container summary (max-width: 450px) {
|
||||
|
@ -263,7 +325,7 @@ main>section#products>article.product>div>div.footer>input {
|
|||
--days: var(--days-short);
|
||||
}
|
||||
|
||||
main>section#summary>div>span:not(#cost, #cost_delivery, #shipping) {
|
||||
/* main>section#summary>div>span:not(#cost, #cost_delivery, #shipping) {
|
||||
display: none;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
|
|
@ -9,15 +9,16 @@
|
|||
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
font-family: "DejaVu";
|
||||
color: var(--tg-theme-text-color);
|
||||
transition: 0.1s ease-out;
|
||||
}
|
||||
|
||||
* {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-family: "DejaVu";
|
||||
color: var(--tg-theme-text-color);
|
||||
transition: 0.1s ease-out;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -70,7 +71,7 @@ main {
|
|||
transition: 0s;
|
||||
}
|
||||
|
||||
main > *.merged {
|
||||
main>*.merged {
|
||||
margin-top: -14px;
|
||||
}
|
||||
|
||||
|
@ -220,15 +221,20 @@ button {
|
|||
background-color: var(--tg-theme-button-color);
|
||||
}
|
||||
|
||||
:is(a[type="button"], button):disabled {
|
||||
filter: contrast(0.7) brightness(0.7);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
a[type="button"] {
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
:is(button, :is(a, label)[type="button"]):is(:hover, :focus) {
|
||||
:is(button, :is(a, label)[type="button"]):not(:disabled):is(:hover, :focus) {
|
||||
filter: brightness(120%);
|
||||
}
|
||||
|
||||
:is(button, :is(a, label)[type="button"]):active {
|
||||
:is(button, :is(a, label)[type="button"]):not(:disabled):active {
|
||||
filter: brightness(80%);
|
||||
transition: 0s;
|
||||
}
|
||||
|
@ -239,6 +245,7 @@ h2 {
|
|||
}
|
||||
|
||||
input {
|
||||
color: var(--tg-theme-text-color);
|
||||
background: unset;
|
||||
}
|
||||
|
||||
|
@ -292,8 +299,8 @@ input {
|
|||
color: var(--tg-theme-hint-color);
|
||||
}
|
||||
|
||||
.deleted {
|
||||
display: none;
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
|
|
|
@ -69,7 +69,6 @@ section#window>div.card>h3>a.exit[type="button"] {
|
|||
}
|
||||
|
||||
section#window>div.card>div.images {
|
||||
--image-width: 10rem;
|
||||
height: 10rem;
|
||||
min-height: 10rem;
|
||||
max-height: 10rem;
|
||||
|
@ -79,10 +78,13 @@ section#window>div.card>div.images {
|
|||
transition: 0s;
|
||||
}
|
||||
|
||||
section#window>div.card>div.images:has(> img:last-child:nth-child(2)) {
|
||||
padding: 0rem 1rem;
|
||||
}
|
||||
|
||||
section#window>div.card>div.images.extend {
|
||||
--image-width: max(30rem, 40vw);
|
||||
z-index: 9999999;
|
||||
left: 0;
|
||||
left: 10vw;
|
||||
top: 10vh;
|
||||
margin: unset !important;
|
||||
position: absolute;
|
||||
|
@ -93,6 +95,7 @@ section#window>div.card>div.images.extend {
|
|||
max-height: 80vh;
|
||||
align-items: center;
|
||||
cursor: default;
|
||||
overflow: unset;
|
||||
transition: 0s;
|
||||
}
|
||||
|
||||
|
@ -102,13 +105,12 @@ section#window>div.card:has(>div.images.extend)>:not(div.images.extend) {
|
|||
|
||||
section#window>div.card>div.images>img {
|
||||
margin-right: 0.5rem;
|
||||
width: var(--image-width);
|
||||
max-width: var(--image-width);
|
||||
min-width: 150px;
|
||||
width: auto;
|
||||
height: 10rem;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
object-fit: contain;
|
||||
object-fit: cover;
|
||||
image-rendering: auto;
|
||||
border-radius: 0.5rem;
|
||||
transition: 0s;
|
||||
|
@ -116,8 +118,9 @@ section#window>div.card>div.images>img {
|
|||
|
||||
section#window>div.card>div.images.extend>img {
|
||||
margin-right: 3vw;
|
||||
width: auto;
|
||||
height: 100%;
|
||||
width: 80vw;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
@ -183,7 +186,6 @@ section#window>div.card>div.footer>button.buy {
|
|||
}
|
||||
|
||||
@container window-footer (max-width: 350px) {
|
||||
|
||||
section#window>div.card>div.footer>small:first-of-type {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
var cdek;
|
||||
var ready = false;
|
||||
var moving = true;
|
||||
|
||||
function init(location) {
|
||||
import('https://cdn.jsdelivr.net/npm/@cdek-it/widget@3')
|
||||
.then(module => {
|
||||
cdek = new window.CDEKWidget({
|
||||
from: {
|
||||
code: 248,
|
||||
address: 'Екатерининская 116'
|
||||
},
|
||||
root: 'map',
|
||||
apiKey: 'a222c5fe-fee7-420a-b979-aec0473a0400',
|
||||
servicePath: 'https://arming.dev.mirzaev.sexy/api/cdek',
|
||||
hideFilters: {
|
||||
have_cashless: true,
|
||||
have_cash: true,
|
||||
is_dressing_room: true,
|
||||
type: false,
|
||||
},
|
||||
hideDeliveryOptions: {
|
||||
office: false,
|
||||
door: false,
|
||||
},
|
||||
lang: '{{ language.name == "ru" ? "rus" : "eng" }}',
|
||||
currency: '{{ currency.name|upper }}',
|
||||
tariffs: {
|
||||
office: [234, 136, 185, 368, 378, 498, 2323, 2360, 510, 291],
|
||||
door: [233, 137, 186, 2322, 294],
|
||||
},
|
||||
defaultLocation: [location?.longitude || {{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.data.longitude ?? 37.622513 }}, location?.latitude || {{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.data.latitude ?? 55.75322 }}],
|
||||
onReady() {
|
||||
// const map = document.getElementById('map');
|
||||
|
||||
// map?.style.setProperty('--animation-end-height', '240px');
|
||||
// map?.classList.add('animated', 'slide-down');
|
||||
},
|
||||
onCalculate(tariffs, address) {
|
||||
// Deleting the delivery cost <span> element
|
||||
document.getElementById("cost_delivery")?.remove();
|
||||
|
||||
// Deleting the delivery days <span> element
|
||||
document.getElementById("shipping")?.remove();
|
||||
|
||||
// Disablind the order button
|
||||
document.getElementById("order")?.setAttribute('disabled', true);
|
||||
},
|
||||
onChoose(type, tariff, address) {
|
||||
moving = false;
|
||||
|
||||
// Deleting the delivery cost <span> element
|
||||
document.getElementById("cost_delivery")?.remove();
|
||||
|
||||
// Deleting the delivery days <span> element
|
||||
document.getElementById("shipping")?.remove();
|
||||
|
||||
// Disablind the order button
|
||||
document.getElementById("order")?.setAttribute('disabled', true);
|
||||
|
||||
core.modules.connect("damper").then(
|
||||
() => {
|
||||
// Imported the damper module
|
||||
|
||||
// Execute under damper
|
||||
if (tariff)
|
||||
core.delivery.write.damper("type", tariff.tariff_code, true);
|
||||
},
|
||||
() => {
|
||||
// Not imported the damper module
|
||||
|
||||
// Execute
|
||||
if (tariff)
|
||||
core.delivery.write.system("type", tariff.tariff_code, true);
|
||||
},
|
||||
);
|
||||
setTimeout(() => {
|
||||
|
||||
//
|
||||
const location = document.getElementById('location');
|
||||
|
||||
if (location instanceof HTMLInputElement) {
|
||||
//
|
||||
|
||||
//
|
||||
location.value = address.city;
|
||||
|
||||
//
|
||||
core.delivery.location(location, false, true);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
//
|
||||
const street = document.getElementById('street');
|
||||
|
||||
if (type === 'office') {
|
||||
//
|
||||
|
||||
if (street instanceof HTMLInputElement) {
|
||||
//
|
||||
|
||||
//
|
||||
street.value = address.address;
|
||||
|
||||
//
|
||||
core.delivery.street(street, true);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
|
||||
if (street instanceof HTMLInputElement) {
|
||||
//
|
||||
|
||||
//
|
||||
street.value = address.name;
|
||||
|
||||
//
|
||||
core.delivery.street(street, true);
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
|
||||
map = true;
|
||||
|
||||
// Initializing the delivery data request <section> element
|
||||
const request = document.getElementById("delivery_request");
|
||||
|
||||
if (request instanceof HTMLElement) {
|
||||
// Initializeg the delivery data request <section> element
|
||||
|
||||
// Hiding the delivery data request <section> element
|
||||
request.classList.add("hidden");
|
||||
}}, 1000);
|
||||
}, 500);
|
||||
}, 500);
|
||||
},
|
||||
});
|
||||
|
||||
{% for product in formatted %}
|
||||
cdek?.addParcel({
|
||||
weight: Math.ceil({{ product.weight is empty ? 0 : product.weight }}),
|
||||
width: Math.ceil({{ product.x is empty ? 0 : product.x }}),
|
||||
height: Math.ceil({{ product.y is empty ? 0 : product.y }}),
|
||||
length: Math.ceil({{ product.z is empty ? 0 : product.z }})
|
||||
});
|
||||
{% endfor %}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('core.telegram.api.location.received', (event) => {
|
||||
if (!ready) {
|
||||
ready = true;
|
||||
init(event.detail.location);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('core.telegram.api.location.rejected', (event) => {
|
||||
if (!ready) {
|
||||
ready = true;
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('core.delivery.calculated', (event) => {
|
||||
if (map && event.detail.json.longitude && event.detail.json.latitude)
|
||||
cdek?.updateLocation([event.detail.json.longitude, event.detail.json.latitude]);
|
||||
});
|
||||
|
||||
document.addEventListener('core.cart.summary.received', (event) => {
|
||||
cdek?.resetParcels();
|
||||
|
||||
for (const product of event.detail.json?.products) {
|
||||
cdek?.addParcel({
|
||||
weight: Math.ceil(product.weight || 0),
|
||||
width: Math.ceil(product.x || 0),
|
||||
height: Math.ceil(product.y || 0),
|
||||
length: Math.ceil(product.z || 0)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() =>
|
||||
{
|
||||
if (!ready) {
|
||||
ready = true;
|
||||
init();
|
||||
}
|
||||
}, 5000);
|
|
@ -0,0 +1,21 @@
|
|||
<section class="cdek column">
|
||||
<div id="address" class="row">
|
||||
<input id="location"
|
||||
class="identifier{% if session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.identifier ?? session.buffer.delivery.location %} success{% endif %}"
|
||||
|
||||
placeholder="{{ language.name == 'ru' ? 'Город' : 'location' }}" value="{{
|
||||
session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.name
|
||||
? session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.name
|
||||
~ ', '
|
||||
~ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.structure|reverse|join(', ')
|
||||
: session.buffer.delivery.location }}"
|
||||
onkeyup="core.delivery.location(this)" oninput="core.delivery.location(this)" tabindex="6" />
|
||||
<input id="street" {% if session.buffer.delivery[account.buffer.delivery.company ??
|
||||
session.buffer.delivery.company].street %} class="success" {% endif %}
|
||||
placeholder="{{ language.name == 'ru' ? 'Улица' : 'Street' }}"
|
||||
value="{{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].street ?? session.buffer.delivery.street }}"
|
||||
onkeyup="core.delivery.street(this)" oninput="core.delivery.street(this)" tabindex="6" />
|
||||
</div>
|
||||
<div id="map" class="rounded">
|
||||
</div>
|
||||
</section>
|
|
@ -3,8 +3,7 @@
|
|||
<div class="column">
|
||||
<div id="deliveries" class="row">
|
||||
{% for identifier, delivery in deliveries %}
|
||||
<input id="{{ identifier }}" name="delivery" type="radio" {% if identifier == (account.buffer.delivery.company ?? session.buffer.delivery.company) %}
|
||||
checked{% endif %}>
|
||||
<input id="{{ identifier }}" name="delivery" type="radio">
|
||||
<label class="rounded" for="{{ identifier }}" type="button"
|
||||
title="{{ (language.name == 'ru' ? 'Выбрать ' : 'Choose ') ~ delivery.label }}"
|
||||
onclick="core.delivery.company(this.previousElementSibling)" tabindex="5">
|
||||
|
@ -12,23 +11,21 @@
|
|||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div id="address" class="row">
|
||||
<input id="location" class="identifier{% if session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.identifier %} success{% endif %}" placeholder="{{ language.name == 'ru' ? 'Город' : 'location' }}"
|
||||
value="{{
|
||||
session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.name
|
||||
? session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.name
|
||||
~ ', '
|
||||
~ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].location.structure|reverse|join(', ')
|
||||
: (session.buffer.delivery.location ?? account.buffer.delivery.location) }}"
|
||||
onkeyup="core.delivery.location(this)" oninput="core.delivery.location(this)" tabindex="6" />
|
||||
<input id="street"{% if session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].street %} class="success"{% endif %} placeholder="{{ language.name == 'ru' ? 'Улица' : 'Street' }}"
|
||||
value="{{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company] ? session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].street : (session.buffer.delivery.street ?? session.buffer.delivery.street) }}"
|
||||
onkeyup="core.delivery.street(this)" oninput="core.delivery.location(this)" tabindex="6" />
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// The document loaded
|
||||
|
||||
setTimeout(() => {
|
||||
// Selecting active delivery company <input> element in the delivery list <div> element
|
||||
document.getElementById('deliveries')?.querySelector('label[for="{{ account.buffer.delivery.company ?? session.buffer.delivery.company }}"]')?.click()
|
||||
}, 300);
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</section>
|
||||
<section id="delivery_request" class="rounded row unselectable merged {% if session.buffer.delivery[account.buffer.delivery.company ??
|
||||
session.buffer.delivery.company].ready %}deleted{% endif %}">
|
||||
<section id="delivery_request" class="rounded row unselectable merged{% if
|
||||
session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].ready!=false %}
|
||||
hidden{% endif %}">
|
||||
<p>
|
||||
<!-- <i class="icon pin small"></i> -->
|
||||
<span>{{ language.name == 'ru' ? 'Укажите данные для доставки' : 'Enter delivery information' }}</span>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{% if cart.products is not empty %}
|
||||
<button id="order" class="rounded merged column unselectable" onclick="core.cart.share(this)" {% if
|
||||
session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].ready==false %}
|
||||
disabled="true" {% endif %}>Оформить заказ</button>
|
||||
{% endif %}
|
|
@ -3,7 +3,7 @@
|
|||
class="rounded column unselectable">
|
||||
<div class="row">
|
||||
<span id="amount">{{ cart.summary.amount ?? 0 }}</span>
|
||||
<span>{{ language.name == "ru" ? "товаров на сумму" : "products worth" }}</span>
|
||||
<span>{{ language.name == "ru" ? "товаров за " : "products worth" }}</span>
|
||||
<span id="cost" class="cost currency">{{ cart.summary.cost ?? 0 }}</span>
|
||||
{% if session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].cost %}
|
||||
<span id="cost_delivery" class="cost delivery currency plus hint">{{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].cost }}</span>
|
||||
|
@ -11,9 +11,6 @@
|
|||
{% if session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].days %}
|
||||
<span id="shipping" class="delivery days hint">{{ session.buffer.delivery[account.buffer.delivery.company ?? session.buffer.delivery.company].days }}</span>
|
||||
{% endif %}
|
||||
<button id="order" onclick="core.cart.share(this)" {% if session.buffer.delivery[account.buffer.delivery.company ??
|
||||
session.buffer.delivery.company].ready == false %} disabled="true" {% endif %}
|
||||
title="{{ language.name == 'ru' ? 'Оформить заказ' : 'Place an order' }}"><i class="icon arrow"></i></button>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<h2 id="title" class="unselectable">{{ h2 }}</h2>
|
||||
{% include "/themes/default/cart/elements/delivery.html" %}
|
||||
{% include "/themes/default/cart/elements/summary.html" %}
|
||||
{% include "/themes/default/cart/elements/order.html" %}
|
||||
{% include "/themes/default/cart/elements/products.html" %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -23,5 +23,5 @@
|
|||
{{ parent() }}
|
||||
<script src="/js/modules/catalog.mjs" type="module"></script>
|
||||
<script src="/js/modules/cart.mjs" type="module"></script>
|
||||
<script src="/js/modules/hotline.js" type="module"></script>
|
||||
<script src="/js/modules/hotline.mjs" type="module"></script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue