Не получается корректно интегрировать подсказки на страницу оформления заказа интернет-магазина на CS-Cart
Добрый день!
Не получается корректно встроить код с вашими подсказками на страницу оформления заказа моего интернет-магазина (на CS-Cart).
В ходе попыток и экспериментов:
а) Закачал файлы, подключаемые в вашем jQuery-плагине себе на сервер;
б) Создал такого Франкенштейна:
<script class="cm-ajax cm-ajax-force cm-ajax-full-render" type="text/javascript" src="/app/dadata/jquery/1.10.2/jquery.min.js" data-no-defer></script> <script class="cm-ajax cm-ajax-force cm-ajax-full-render" type="text/javascript" src="/app/dadata/dist/js/jquery.suggestions.min.js" data-no-defer></script> <link class="cm-ajax cm-ajax-force cm-ajax-full-render" rel="stylesheet" href="/app/dadata/dist/css/suggestions.min.css" data-no-defer> <script class="cm-ajax cm-ajax-force" type="text/javascript" data-no-defer> /** * Показывает индекс в отдельном поле */ function showPostalCode(suggestion) { $("#elm_29").val(suggestion.data.postal_code); } /** * Очищает индекс */ function clearPostalCode(suggestion) { $("#elm_29").val(""); } function join(arr /*, separator */ ) { var separator = arguments.length > 1 ? arguments[1] : ", "; return arr.filter(function(n) { return n }).join(separator); } function makeAddressString(address) { if (address.settlement) { return join([ address.city, address.settlement ]) } else { return join([ address.city, ]) } } function formatResult(value, currentValue, suggestion) { var addressValue = makeAddressString(suggestion.data); suggestion.value = addressValue; return addressValue; } function formatSelected(suggestion) { var addressValue = makeAddressString(suggestion.data); return addressValue; } var token = "63aca8e5a32834498b49fadbbbc3d8fd69811ec4", type = "ADDRESS", $city = $("#elm_23"), $street = $("#elm_19"); // город и населенный пункт $city.suggestions({ token: token, type: type, hint: false, bounds: "city-settlement", formatResult: formatResult, formatSelected: formatSelected, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); // улица $street.suggestions({ token: token, type: type, hint: false, bounds: "street-house", constraints: $city, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); </script>
В CS-Cart страница оформления заказа состоит из четырех шагов - регистрация/авторизация (шаг 1), адрес доставки/адрес плательщика (шаг 2), выбор способа доставки, выбор способа оплаты. При загрузке страницы попадаешь на один из этих четырех шагов (в зависимости от заполненности профиля и сохраненных кук), остальные три шага подгружаются через ajax.
Соответственно, вставил этот код в шаблон второго шага, получилось следующее:
{if $show_email} <div class="ty-control-group"> <label for="{$id_prefix}elm_email" class="cm-required cm-email">{__("email")}<i>*</i></label> <input type="text" id="{$id_prefix}elm_email" name="user_data[email]" size="32" value="{$user_data.email}" class="ty-input-text {$_class}" {$disabled_param} /> </div> {else} {if $profile_fields.$section} {if $address_flag} <div class="ty-profile-field__switch ty-address-switch clearfix"> <div class="ty-profile-field__switch-label">{if $section == "S"}{__("shipping_same_as_billing")}{else}{__("text_billing_same_with_shipping")}{/if}</div> <div class="ty-profile-field__switch-actions"> <input class="radio cm-switch-availability cm-switch-inverse cm-switch-visibility" type="radio" name="ship_to_another" value="0" id="sw_{$body_id}_suffix_yes" {if !$ship_to_another}checked="checked"{/if} /><label for="sw_{$body_id}_suffix_yes">{__("yes")}</label> <input class="radio cm-switch-availability cm-switch-visibility" type="radio" name="ship_to_another" value="1" id="sw_{$body_id}_suffix_no" {if $ship_to_another}checked="checked"{/if} /><label for="sw_{$body_id}_suffix_no">{__("no")}</label> </div> </div> {else} <input type="hidden" name="ship_to_another" value="1" /> {/if} {if ($address_flag && !$ship_to_another && ($section == "S" || $section == "B")) || $disabled_by_default} {assign var="disabled_param" value="disabled=\"disabled\""} {assign var="_class" value="disabled"} {assign var="hide_fields" value=true} {else} {assign var="disabled_param" value=""} {assign var="_class" value=""} {/if} <div class="clearfix"> {if $body_id || $grid_wrap} <div id="{$body_id}" class="{if $hide_fields}hidden{/if}"> <div class="{$grid_wrap}"> {/if} {if !$nothing_extra} {include file="common/subheader.tpl" title=$title} {/if} {foreach from=$profile_fields.$section item=field name="profile_fields"} {if $field.field_name && $field.is_default == 'Y'} {assign var="data_name" value="user_data"} {assign var="data_id" value=$field.field_name} {assign var="value" value=$user_data.$data_id} {else} {assign var="data_name" value="user_data[fields]"} {assign var="data_id" value=$field.field_id} {assign var="value" value=$user_data.fields.$data_id} {/if} {assign var="skip_field" value=false} {if $section == "S" || $section == "B"} {if $section == "S"} {assign var="_to" value="B"} {else} {assign var="_to" value="S"} {/if} {if !$profile_fields.$_to[$field.matching_id]} {assign var="skip_field" value=true} {/if} {/if} {hook name="profiles:profile_fields"} <div class="ty-control-group ty-profile-field__item ty-{$field.class}"> <script class="cm-ajax cm-ajax-force" type="text/javascript" data-no-defer> function dadata(){ var jqm = document.createElement('script'), jqs = document.createElement('script'), ssm = document.createElement('style'); jqm.class = 'cm-ajax cm-ajax-force cm-ajax-full-render'; jqm.type = 'text/javascript'; jqm.async = true; jqm.src = '/app/dadata/jquery/1.10.2/jquery.min.js'; jqs.class = 'cm-ajax cm-ajax-force cm-ajax-full-render' jqs.type = 'text/javascript'; jqs.async = true; jqs.src = '/app/dadata/dist/js/jquery.suggestions.min.js'; ssm.class = 'cm-ajax cm-ajax-force cm-ajax-full-render' ssm.rel = 'stylesheet'; ssm.href = '/app/dadata/dist/css/suggestions.min.css'; /** * Показывает индекс в отдельном поле */ function showPostalCode(suggestion) { $("#elm_29").val(suggestion.data.postal_code); } /** * Очищает индекс */ function clearPostalCode(suggestion) { $("#elm_29").val(""); } function join(arr /*, separator */ ) { var separator = arguments.length > 1 ? arguments[1] : ", "; return arr.filter(function(n) { return n }).join(separator); } function makeAddressString(address) { if (address.settlement) { return join([ address.city, address.settlement ]) } else { return join([ address.city, ]) } } function formatResult(value, currentValue, suggestion) { var addressValue = makeAddressString(suggestion.data); suggestion.value = addressValue; return addressValue; } function formatSelected(suggestion) { var addressValue = makeAddressString(suggestion.data); return addressValue; } var token = "63aca8e5a32834498b49fadbbbc3d8fd69811ec4", type = "ADDRESS", $city = $("#elm_23"), $street = $("#elm_19"); // город и населенный пункт $city.suggestions({ token: token, type: type, hint: false, bounds: "city-settlement", formatResult: formatResult, formatSelected: formatSelected, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); // улица $street.suggestions({ token: token, type: type, hint: false, bounds: "street-house", constraints: $city, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); } </script> {if $pref_field_name != $field.description || $field.required == "Y"} <label for="{$id_prefix}elm_{$field.field_id}" class="ty-control-group__title cm-profile-field {if $field.required == "Y"}cm-required{/if}{if $field.field_type == "P"} cm-phone{/if}{if $field.field_type == "Z"} cm-zipcode{/if}{if $field.field_type == "E"} cm-email{/if} {if $field.field_type == "Z"}{if $section == "S"}cm-location-shipping{else}cm-location-billing{/if}{/if}">{$field.description}</label> {/if} {if $field.field_type == "A"} {* State selectbox *} {$_country = $settings.General.default_country} {$_state = $value|default:$settings.General.default_state} <select {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} id="{$id_prefix}elm_{$field.field_id}" class="ty-profile-field__select-state cm-state {if $section == "S"}cm-location-shipping{else}cm-location-billing{/if} {if !$skip_field}{$_class}{/if}" name="{$data_name}[{$data_id}]" {if !$skip_field}{$disabled_param nofilter}{/if}> <option value="">- {__("select_state")} -</option> {if $states && $states.$_country} {foreach from=$states.$_country item=state} <option {if $_state == $state.code}selected="selected"{/if} value="{$state.code}">{$state.state}</option> {/foreach} {/if} </select><input {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} type="text" id="elm_{$field.field_id}_d" name="{$data_name}[{$data_id}]" size="32" maxlength="64" value="{$_state}" disabled="disabled" class="cm-state {if $section == "S"}cm-location-shipping{else}cm-location-billing{/if} ty-input-text hidden {if $_class}disabled{/if}"/> {elseif $field.field_type == "O"} {* Countries selectbox *} {assign var="_country" value=$value|default:$settings.General.default_country} <select {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} id="{$id_prefix}elm_{$field.field_id}" class="ty-profile-field__select-country cm-country {if $section == "S"}cm-location-shipping{else}cm-location-billing{/if} {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if}" name="{$data_name}[{$data_id}]" {if !$skip_field}{$disabled_param nofilter}{/if}> {hook name="profiles:country_selectbox_items"} <option value="">- {__("select_country")} -</option> {foreach from=$countries item="country" key="code"} <option {if $_country == $code}selected="selected"{/if} value="{$code}">{$country}</option> {/foreach} {/hook} </select> {elseif $field.field_type == "C"} {* Checkbox *} <input type="hidden" name="{$data_name}[{$data_id}]" value="N" {if !$skip_field}{$disabled_param nofilter}{/if} /> <input type="checkbox" id="{$id_prefix}elm_{$field.field_id}" name="{$data_name}[{$data_id}]" value="Y" {if $value == "Y"}checked="checked"{/if} class="checkbox {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if}" {if !$skip_field}{$disabled_param nofilter}{/if} /> {elseif $field.field_type == "T"} {* Textarea *} <textarea {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} class="ty-input-textarea {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if}" id="{$id_prefix}elm_{$field.field_id}" name="{$data_name}[{$data_id}]" cols="32" rows="3" {if !$skip_field}{$disabled_param nofilter}{/if}>{$value}</textarea> {elseif $field.field_type == "D"} {* Date *} {if !$skip_field} {include file="common/calendar.tpl" date_id="`$id_prefix`elm_`$field.field_id`" date_name="`$data_name`[`$data_id`]" date_val=$value extra=$disabled_param} {else} {include file="common/calendar.tpl" date_id="`$id_prefix`elm_`$field.field_id`" date_name="`$data_name`[`$data_id`]" date_val=$value} {/if} {elseif $field.field_type == "S"} {* Selectbox *} <select {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} id="{$id_prefix}elm_{$field.field_id}" class="ty-profile-field__select {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if}" name="{$data_name}[{$data_id}]" {if !$skip_field}{$disabled_param nofilter}{/if}> {if $field.required != "Y"} <option value="">--</option> {/if} {foreach from=$field.values key=k item=v} <option {if $value == $k}selected="selected"{/if} value="{$k}">{$v}</option> {/foreach} </select> {elseif $field.field_type == "R"} {* Radiogroup *} <div id="{$id_prefix}elm_{$field.field_id}"> {foreach from=$field.values key=k item=v name="rfe"} <input class="radio {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if} {$id_prefix}elm_{$field.field_id}" type="radio" id="{$id_prefix}elm_{$field.field_id}_{$k}" name="{$data_name}[{$data_id}]" value="{$k}" {if (!$value && $smarty.foreach.rfe.first) || $value == $k}checked="checked"{/if} {if !$skip_field}{$disabled_param nofilter}{/if} /><span class="radio">{$v}</span> {/foreach} </div> {elseif $field.field_type == "N"} {* Address type *} <input class="radio {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if} {$id_prefix}elm_{$field.field_id}" type="radio" id="{$id_prefix}elm_{$field.field_id}_residential" name="{$data_name}[{$data_id}]" value="residential" {if !$value || $value == "residential"}checked="checked"{/if} {if !$skip_field}{$disabled_param nofilter}{/if} /><span class="radio">{__("address_residential")}</span> <input class="radio {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if} {$id_prefix}elm_{$field.field_id}" type="radio" id="{$id_prefix}elm_{$field.field_id}_commercial" name="{$data_name}[{$data_id}]" value="commercial" {if $value == "commercial"}checked="checked"{/if} {if !$skip_field}{$disabled_param nofilter}{/if} /><span class="radio">{__("address_commercial")}</span> {else} {* Simple input *} <input {if $field.autocomplete_type}x-autocompletetype="{$field.autocomplete_type}"{/if} type="text" id="{$id_prefix}elm_{$field.field_id}" name="{$data_name}[{$data_id}]" size="32" value="{$value}" class="ty-input-text {if !$skip_field}{$_class}{else}cm-skip-avail-switch{/if} {if $smarty.foreach.profile_fields.index == 0} cm-focus{/if}" {if !$skip_field}{$disabled_param nofilter}{/if} /> {/if} {assign var="pref_field_name" value=$field.description} </div> {/hook} {/foreach} <script class="cm-ajax cm-ajax-force cm-ajax-full-render" type="text/javascript" src="/app/dadata/jquery/1.10.2/jquery.min.js" data-no-defer></script> <script class="cm-ajax cm-ajax-force cm-ajax-full-render" type="text/javascript" src="/app/dadata/dist/js/jquery.suggestions.min.js" data-no-defer></script> <link class="cm-ajax cm-ajax-force cm-ajax-full-render" rel="stylesheet" href="/app/dadata/dist/css/suggestions.min.css" data-no-defer> <script class="cm-ajax cm-ajax-force" type="text/javascript" data-no-defer> /** * Показывает индекс в отдельном поле */ function showPostalCode(suggestion) { $("#elm_29").val(suggestion.data.postal_code); } /** * Очищает индекс */ function clearPostalCode(suggestion) { $("#elm_29").val(""); } function join(arr /*, separator */ ) { var separator = arguments.length > 1 ? arguments[1] : ", "; return arr.filter(function(n) { return n }).join(separator); } function makeAddressString(address) { if (address.settlement) { return join([ address.city, address.settlement ]) } else { return join([ address.city, ]) } } function formatResult(value, currentValue, suggestion) { var addressValue = makeAddressString(suggestion.data); suggestion.value = addressValue; return addressValue; } function formatSelected(suggestion) { var addressValue = makeAddressString(suggestion.data); return addressValue; } var token = "63aca8e5a32834498b49fadbbbc3d8fd69811ec4", type = "ADDRESS", $city = $("#elm_23"), $street = $("#elm_19"); // город и населенный пункт $city.suggestions({ token: token, type: type, hint: false, bounds: "city-settlement", formatResult: formatResult, formatSelected: formatSelected, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); // улица $street.suggestions({ token: token, type: type, hint: false, bounds: "street-house", constraints: $city, onSelect: showPostalCode, onSelectNothing: clearPostalCode }); </script> {if $body_id || $grid_wrap} </div> </div> {/if} </div> {/if} {/if}
В итоге:
а) Если загружать страницу оформления заказа и попадать сразу на второй шаг - все работает отлично. Так бывает, если например пользователь уже залогинен, но у него в профиле не указаны данные по адресу доставки;
б) Если загружать чекаут и попадать на первый, третий или четвертый шаг, и уже с помощью ajax-а возвращаться на второй - то работать все перестает и страница виснет. Консоль выдает следующее:
Уверен, что должно быть какое-то простое решение, как с этим бороться. Может сможете помочь?
Ответ
Добрый день! Несколько вопросов:
- Код инициализации подсказок дублируется дважды. Один раз внутри хука profiles:profile_fields, второй — без хуков внизу шаблона. Зачем?
- В каких случаях вызывается хук profiles:profile_fields?
- Дайте, пожалуйста, ссылку на сайт, где можно увидеть описанное поведение в действии.
Сервис поддержки клиентов работает на платформе UserEcho
Добрый день! Несколько вопросов: