public function execute() { $this->response = array('options' => array(), 'oOrder' => array()); $country = waRequest::request('country'); if (!$country) { return; } $rm = new waRegionModel(); foreach ($rm->getByCountryWithFav($country) as $row) { if ($row['name'] === '') { $this->response['options'][''] = ' '; $this->response['oOrder'][] = ''; } else { $this->response['options'][$row['code']] = $row['name']; $this->response['oOrder'][] = $row['code']; } } }
public function getHtmlOne($params = array(), $attrs = '') { $value = isset($params['value']) ? $params['value'] : ''; $ext = null; $multi_suffix = ''; if (is_array($value)) { $ext = $value['ext']; $value = $value['value']; } $name_input = $name = $this->getHTMLName($params); if ($this->isMulti()) { $name_input .= '[value]'; } $country = ifset($params['composite_value']['country']); $region_countries = array_fill_keys($this->getRegionCountries(), 1); if (!$region_countries || empty($country) && empty($params['parent'])) { // The simplest case: just show <input> with no logic at all. return '<input type="text" name="' . htmlspecialchars($name_input) . '" value="' . htmlspecialchars($value) . '" ' . $attrs . '>'; } // // So, we're a part of a composite field with a Country subfield. // Need to show <select> with regions, if selected country has them, // or <input> when no country selected or has no regions. // In case user changes the country, we should load new regions via XHR. // And on top of that, field should behave reasonably when JS is off! // // When country is selected and has regions, build a <select> with appropriate options. $region_select = null; if ($country) { // List of regions for this country $rm = new waRegionModel(); $options = array('<option value="">' . htmlspecialchars('<' . _ws('select region') . '>') . '</option>'); $selected = false; foreach ($rm->getByCountryWithFav($country) as $row) { if (strlen($row['name']) <= 0) { $options[] = '<option disabled> </option>'; } else { if (!$selected && ($value == $row['code'] || $value == $row['name'])) { $at = ' selected'; $selected = true; } else { $at = ''; } $options[] = '<option value="' . htmlspecialchars($row['code']) . '"' . $at . '>' . htmlspecialchars($row['name']) . '</option>'; } } if (count($options) > 1) { // Selected country has regions. Show as <select>. $region_select = '<select name="' . htmlspecialchars($name_input) . '" ' . $attrs . ">\n\t" . implode("\n\t", $options) . "\n</select>"; } } $html = ''; if ($region_select) { // Selected country has regions. Select field with regions is visible. // There's a hidden <input> to switch to when user changes country. $html .= $region_select; $html .= '<input type="text" ' . $attrs . ' style="display:none;">'; } else { // No country selected or country has no regions. // <input> is visible and <select> is hidden. $html .= '<select ' . $attrs . ' style="display:none;"></select>'; $html .= '<input type="text" name="' . htmlspecialchars($name_input) . '" value="' . htmlspecialchars($value) . '" ' . $attrs . '>'; } // JS to load regions when user changes country. $p = $params; $p['id'] = 'country'; $name_country = $this->getHTMLName($p); if (wa()->getEnv() == 'backend') { $xhr_url = ifset($params['xhr_url'], wa()->getAppUrl('webasyst') . '?module=backend&action=regions'); } else { $xhr_url = ifset($params['xhr_url'], wa()->getRouteUrl('/frontend/regions')); } $region_countries = json_encode($region_countries); $empty_option = '<' . _ws('select region') . '>'; $js = <<<EOJS <script>if(\$){ \$(function() { var region_countries = {$region_countries}; var input_name = "{$name_input}"; var country_select = \$('[name="{$name_country}"]'); var xhr_url = "{$xhr_url}"; if (country_select.length <= 0) { return; } var select; var input = \$('[name="'+input_name+'"]'); if (input.length <= 0) { return; } if (input.is('input')) { select = input.prev(); } else { select = input; input = select.next(); } var showInput = function() { if (!input[0].hasAttribute('name')) { input.attr('name', select.attr('name')) select[0].removeAttribute('name'); } input.show().val(''); select.hide(); }; var getVal = function() { if (input.is(':visible')) { return input.val(); } else { return select.val(); } }; var change_handler; country_select.change(change_handler = function() { var old_val = getVal(); var country = country_select.val(); input.prev('.loading').remove(); if (region_countries && region_countries[country]) { showInput(); input.before('<i class="icon16 loading"></i>'); \$.post(xhr_url, { country: country }, function(r) { input.prev('.loading').remove(); if (r.data && r.data.options && r.data.oOrder) { input.hide(); select.show().children().remove(); select.append(\$('<option value=""></option>').text("{$empty_option}")); var o, selected = false; for (i = 0; i < r.data.oOrder.length; i++) { o = \$('<option></option>').attr('value', r.data.oOrder[i]).text(r.data.options[r.data.oOrder[i]]).attr('disabled', r.data.oOrder[i] === ''); if (!selected && old_val === r.data.oOrder[i]) { o.attr('selected', true); selected = true; } select.append(o); } if (input[0].hasAttribute('name')) { select.attr('name', input.attr('name')); input[0].removeAttribute('name'); } } else { showInput(); input.val(old_val); } }, 'json'); } else { if (!input.is(':visible')) { showInput(); input.val(old_val); } } }); change_handler.call(country_select); });};</script> EOJS; return $html . $js; }
public function getHtmlOne($params = array(), $attrs = '') { $value = isset($params['value']) ? $params['value'] : ''; $ext = null; $multi_suffix = ''; if (is_array($value)) { $ext = $value['ext']; $value = $value['value']; } if (preg_match('~(?:\\s|")id="([^"]+)"~', ' ' . $attrs, $matches)) { $select_id = $matches[1]; $attrs = trim(preg_replace('~(\\s|")id="([^"]+)"~', '$1 ', ' ' . $attrs)); } else { $select_id = uniqid('s'); } $input_id = $select_id . '-input'; $name_input = $name = $this->getHTMLName($params); if ($this->isMulti()) { $name_input .= '[value]'; } $country = ifset($params['composite_value']['country']); $region_countries = array_fill_keys($this->getRegionCountries(), 1); if (!$region_countries || empty($country) && empty($params['parent'])) { // The simplest case: just show <input> with no logic at all. return '<input type="text" name="' . htmlspecialchars($name_input) . '" value="' . htmlspecialchars($value) . '" ' . $attrs . '>'; } // // So, we're a part of a composite field with a Country subfield. // Need to show <select> with regions, if selected country has them, // or <input> when no country selected or has no regions. // In case user changes the country, we should load new regions via XHR. // And on top of that, field should behave reasonably when JS is off! // // When country is selected and has regions, build a <select> with appropriate options. $region_select = null; if ($country && !is_array($country)) { // List of regions for this country $rm = new waRegionModel(); $options = array('<option value="">' . htmlspecialchars('<' . _ws('select region') . '>') . '</option>'); $selected = false; foreach ($rm->getByCountryWithFav($country) as $row) { if (strlen($row['name']) <= 0) { $options[] = '<option disabled> </option>'; } else { if (!$selected && ($value == $row['code'] || $value == $row['name'])) { $at = ' selected'; $selected = true; } else { $at = ''; } $options[] = '<option value="' . htmlspecialchars($row['code']) . '"' . $at . '>' . htmlspecialchars($row['name']) . '</option>'; } } if (count($options) > 1) { // Selected country has regions. Show as <select>. $region_select = '<select name="' . htmlspecialchars($name_input) . '" data-country="' . htmlspecialchars($country) . '" id="' . $select_id . '" ' . $attrs . ">\n\t" . implode("\n\t", $options) . "\n</select>"; } } $html = ''; if ($region_select) { // Selected country has regions. Select field with regions is visible. // There's a hidden <input> to switch to when user changes country. $html .= $region_select; $html .= '<input type="text" id="' . $input_id . '" ' . $attrs . ' style="display:none;">'; } else { // No country selected or country has no regions. // <input> is visible and <select> is hidden. $html .= '<select id="' . $select_id . '" ' . $attrs . ' style="display:none;"></select>'; $html .= '<input type="text" id="' . $input_id . '" name="' . htmlspecialchars($name_input) . '" value="' . htmlspecialchars($value) . '" ' . $attrs . '>'; } // JS to load regions when user changes country. $p = $params; $p['id'] = 'country'; $name_country = $this->getHTMLName($p); if (wa()->getEnv() == 'backend') { $xhr_url = ifset($params['xhr_url'], wa()->getAppUrl('webasyst') . '?module=backend&action=regions'); } else { $xhr_url = ifset($params['xhr_url'], wa()->getRouteUrl('/frontend/regions')); } $crossDomain = ifset($params['xhr_cross_domain'], 0); $dataType = isset($params['xhr_cross_domain']) ? 'jsonp' : 'json'; $region_countries = str_replace("{", "{ ", str_replace("}", " }", json_encode($region_countries))); $empty_option = '<' . _ws('select region') . '>'; $js = <<<EOJS <script>if(\$){ \$(function() { // List of countries we have regions for var region_countries = {$region_countries}; // Country selector regions depend on var country_select = \$('[name="{$name_country}"]'); if (country_select.length <= 0) { return; } // <select> and <input> fields that are parts of this region controller var select = \$('#{$select_id}'); var input = \$('#{$input_id}'); if (input.length <= 0 || select.length <= 0) { return; } // URL to fetch list of regions from var xhr_url = "{$xhr_url}"; // Helper to hide <select> and show <input> var showInput = function(val) { if (!input[0].hasAttribute('name')) { input.attr('name', select.attr('name')) select[0].removeAttribute('name'); } input.show().val(val || ''); select.hide(); }; // Helper to hide <input> and show <select> var showSelect = function() { if (input[0].hasAttribute('name')) { select.attr('name', input.attr('name')); input[0].removeAttribute('name'); } select.show(); input.hide(); }; // Returns currently selected value of <select> or value of <input> var getVal = function() { if (input.is(':visible')) { return input.val(); } else { return select.val(); } }; // When user changes country, update region selector. var change_handler; country_select.change(change_handler = function() { var old_val = getVal(); // previous user-selected option in <select> or value of <input> var country = country_select.val(); input.prev('.loading').remove(); // When <select> already has regions for this country loaded, just show it without XHR. var previously_selected = select.data('country'); if (previously_selected && country == previously_selected) { showSelect(); return; } if (region_countries && region_countries[country]) { // Selected country has regions. Load them into <select> via XHR. showInput(''); input.before('<i class="icon16 loading"></i>'); \$.ajax(xhr_url, { type: 'post', crossDomain: {$crossDomain}, data: { country: country }, dataType: '{$dataType}', success: function(r) { input.prev('.loading').remove(); if (r.data && r.data.options && r.data.oOrder) { select.children().remove(); select.append(\$('<option value=""></option>').text("{$empty_option}")); var o, selected = false; for (i = 0; i < r.data.oOrder.length; i++) { o = \$('<option></option>').attr('value', r.data.oOrder[i]).text(r.data.options[r.data.oOrder[i]]).attr('disabled', r.data.oOrder[i] === ''); if (!selected && old_val === r.data.oOrder[i]) { o.attr('selected', true); selected = true; } select.append(o); } select.data('country', country); showSelect(); } else { showInput(''); } } }); } else { // Selected country has no regions. Show <input>. if (!input.is(':visible')) { showInput(''); } } }); change_handler.call(country_select[0]); });};</script> EOJS; return $html . $js; }