Jump to content

  • You cannot start a new topic
  • You cannot reply to this topic

Drop Down Select City Rate Topic   - - - - -

 

Posted 10 June 2011 - 06:26 PM #1

Hi Everybody.

Anybody can help how to create or configure drop down select city like drop down select state ?


Thanks

 
  • tbirnseth
  • CS Cart Expert
  • Authorized Reseller
  • Join Date: 08-Nov 08
  • 10551 posts

Posted 10 June 2011 - 11:49 PM #2

Only if you want to enter every city into a database table.....

EZ Merchant Solutions: Custom (USA based) B2B Development, Consulting, Development and Special Projects (get a quote here).
Commercial addons, payment methods and modifications to meet your business and operations needs.


 

Posted 11 June 2011 - 05:02 AM #3

Only if you want to enter every city into a database table.....


No problem to enter every city, but, how can to make drop down menu select city ?

eg.

STATE A
city AAA
city ABB
city ACC

STATE B
city BBB
city BCC
city BDD

so, if user select STATE B, so, City drop down only can choose :
city BBB
city BCC
city BDD

Can Help me sir ??

 
  • tbirnseth
  • CS Cart Expert
  • Authorized Reseller
  • Join Date: 08-Nov 08
  • 10551 posts

Posted 11 June 2011 - 05:18 PM #4

Well, this is custom work.

I can tell you how to do it, but to do it requires development skills. If you have them, you can do it. If not, then you'll have to hire it out.

You'll need to copy the schema for the cscart_states file to cscart_cities.
You'll need to add a field for state_code and change state_id to city_id.
You will then need to add a php function that can build the list of cities using the coutnry_code and state_code (see core/fn.locations.php, function fn_get_states() as an example).
You will need to modify the code that sets 'locations' in the Registry.
You will then need to modify every template that references '$lang.city' and uses an 'input' box to use a 'select' and then create a new template that will build the correct selector. This select must use the same 'onchange' mechanisms as the 'country' select that rebuilds the state selector, so that when a country or state is changed, the city selector is updated via ajax.

It's probably 6-10 hours of work depending on ones familiarity with cs-cart, the templates, their jQuery (old version) and other cart details.

Of course, then you'd have to build the admin interface that would allow you to build your cities, assigning country codes and state codes for each list.

EZ Merchant Solutions: Custom (USA based) B2B Development, Consulting, Development and Special Projects (get a quote here).
Commercial addons, payment methods and modifications to meet your business and operations needs.


 
  • evinik
  • Newbie
  • Trial users
  • Join Date: 31-Oct 11
  • 8 posts

Posted 01 June 2012 - 07:38 AM #5

Can anyone help me, how exactly can I do this? I really need a city-list dropdown. Any help will be appreciated. Thank you in advance

 
  • dioskouros
  • Member
  • Members
  • Join Date: 21-Jul 10
  • 52 posts

Posted 13 February 2014 - 02:36 PM #6

That's very interesting.

I did some experiments according to tbirnseth's usefull thoughts.

The target is to alter city input field to select box dependent to state selection.

But does the locations' functionality about cities wildcards remain the same ?? Because the final target is, on city selection to calculate the shipping cost of an order at checkout step,

So I created a table like this

DROP TABLE IF EXISTS `katoikia`.`cscart_cities`;
CREATE TABLE  `katoikia`.`cscart_cities` (
  `city_id` mediumint(<img src='http://forum.cs-cart.com/public/style_emoticons/<#EMO_DIR#>/icon_cool.gif' class='bbc_emoticon' alt='8)' /> unsigned NOT NULL auto_increment,
  `country_code` varchar(2) NOT NULL default '',
  `code` varchar(32) NOT NULL default '',
  `state_id` varchar(32) NOT NULL,
  `status` char(1) NOT NULL default 'A',
  PRIMARY KEY  (`city_id`),
  UNIQUE KEY `cs` (`country_code`,`code`),
  KEY `code` (`code`),
  KEY `country_code` (`country_code`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

then I added functions for bulding and seeking cities, almost like every state function at core/fn.locations.php like that:

//
// Get countries list
//
function fn_get_countries($lang_code = CART_LANGUAGE, $only_avail = false, $paginate = false)
{
$only_avail = ($only_avail == true) ? " WHERE a.status = 'A'" : '';
$limit = '';
$page = empty($_REQUEST['page']) ? 1 : $_REQUEST['page'];
if ($paginate == true) {
  $country_count = db_get_field("SELECT count(*) FROM ?:countries");
  $limit = fn_paginate($page, $country_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.code, a.code_A3, a.code_N3, a.status, a.region, b.country FROM ?:countries as a LEFT JOIN ?:country_descriptions as b ON b.code = a.code AND b.lang_code = ?s $only_avail ORDER BY b.country $limit", $lang_code);
}
//
// Get countries simple list
//
function fn_get_simple_countries($avail_only = false, $lang_code = CART_LANGUAGE)
{
$avail_cond = ($avail_only == true)  ? "WHERE a.status = 'A'" : '';
return db_get_hash_single_array("SELECT a.code, b.country FROM ?:countries as a LEFT JOIN ?:country_descriptions as b ON b.code = a.code AND b.lang_code = ?s $avail_cond ORDER BY b.country", array('code', 'country'), $lang_code);
}
//
// Get states list for specific country
//
function fn_get_states($country = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($country)) {
  return '';
}
$limit = '';
if ($paginate == true) {
  $state_count = db_get_field("SELECT COUNT(*) FROM ?:states WHERE country_code = ?s", $country);
  $limit = fn_paginate(@$_REQUEST['page'], $state_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.state_id, a.country_code, a.code, a.status, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s WHERE a.country_code = ?s ORDER BY b.state $limit", $lang_code, $country);
}
//
// Get cities list for specific state
//
function fn_get_cities($state = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($state)) {
  return '';
}
$limit = '';
if ($paginate == true) {
  $city_count = db_get_field("SELECT COUNT(*) FROM ?:cities WHERE state_id = ?s", $state);
  $limit = fn_paginate(@$_REQUEST['page'], $city_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.city_id, a.country_code, a.code, a.state_id, a.status
FROM ?:cities as a WHERE a.country_code = ?s AND a.state_id = ?s ORDER BY a.code $limit", $country, $state);
}

//
// Get states key-value list
//
function fn_get_simple_states($country = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($country)) {
  $country = 'US'; //!!! FIXME: what is the logic should be?
}
return db_get_hash_single_array("SELECT a.code, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s WHERE a.country_code = ?s ORDER BY b.state", array('code', 'state'), $lang_code, $country);
}
//
// Get cities key-value list
//
function fn_get_simple_cities($state = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($state)) {
  $state = ''; //!!! FIXME: what is the logic should be?
}
return db_get_hash_single_array("SELECT a.city_id, a.code FROM ?:cities as a WHERE a.state_id = ?s ORDER BY a.code", array('city_id', 'code'), $state);
}
//
// Get states list for specific country
//
function fn_get_all_states($lang_code = CART_LANGUAGE, $extended = false, $avail_only = true)
{
$avail_cond = ($avail_only == true) ? " WHERE a.status = 'A' " : '';
if ($extended == true) {
  return db_get_array("SELECT a.state_id, a.code, b.state, c.country FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s LEFT JOIN ?:country_descriptions as c ON c.code = a.country_code AND c.lang_code = ?s $avail_cond ORDER BY a.country_code, b.state", $lang_code, $lang_code);
} else {
  return db_get_hash_multi_array("SELECT a.country_code, a.code, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s $avail_cond ORDER BY a.country_code, b.state", array('country_code'), $lang_code);
}
}
//
// Get cities list for specific state
//
function fn_get_all_cities($lang_code = CART_LANGUAGE, $extended = false, $avail_only = true)
{
$avail_cond = ($avail_only == true) ? " WHERE a.status = 'A' " : '';
if ($extended == true) {
  return db_get_array("SELECT a.city_id, a.code, a.state_id, b.state, c.country FROM ?:cities as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s LEFT JOIN ?:country_descriptions as c ON c.code = a.country_code AND c.lang_code = ?s ORDER BY a.country_code, b.state", $lang_code, $lang_code);
} else {
  return db_get_hash_multi_array("SELECT a.country_code, a.state_id, a.city_id, a.code FROM ?:cities as a ORDER BY a.country_code, a.code", array('state_id'), $lang_code);
}
}

// Get state name (results are cached)
function fn_get_state_name($state_code, $country_code, $lang_code = CART_LANGUAGE)
{
static $states = array();
if (!isset($states[$country_code][$state_code])) {
  $states[$country_code][$state_code] = db_get_field("SELECT ?:state_descriptions.state FROM ?:states LEFT JOIN ?:state_descriptions ON ?:state_descriptions.state_id = ?:states.state_id AND ?:state_descriptions.lang_code = ?s WHERE ?:states.country_code = ?s AND ?:states.code = ?s", $lang_code, $country_code, $state_code);
}
return $states[$country_code][$state_code];
}
// Get city name (results are cached)
function fn_get_city_name($state_id, $country_code)
{
static $cities = array();
if (!isset($cities[$country_code][$state_id])) {
  $cities[$country_code][$state_id] = db_get_field("SELECT ?:cities.code FROM ?:cities WHERE ?:cities.country_code = ?s AND ?:cities.state_id = ?s", $country_code, $state_id);
}
return $cities[$country_code][$state_id];
}

// Get country name (results are cached)
function fn_get_country_name($country_code, $lang_code = CART_LANGUAGE)
{
static $countries = array();
if (empty($countries[$country_code])) {
  $countries[$country_code] = db_get_field("SELECT country FROM ?:country_descriptions WHERE code = ?s AND lang_code = ?s", $country_code, $lang_code);
}

return $countries[$country_code];
}
// Get countries name (results are cached)
function fn_get_countries_name($country_codes, $lang_code = CART_LANGUAGE)
{
$countries = db_get_hash_array("SELECT country, code FROM ?:country_descriptions WHERE code IN (?a) AND lang_code = ?s", 'code', $country_codes, $lang_code);
return $countries;
}
//
// Get all destinations list
//
function fn_get_destinations($lang_code = CART_LANGUAGE)
{
$destinations = db_get_hash_array("SELECT a.destination_id, a.status, a.localization, b.destination FROM ?:destinations as a LEFT JOIN ?:destination_descriptions as b ON a.destination_id = b.destination_id AND b.lang_code = ?s ORDER BY destination", 'destination_id', $lang_code);
$default = $destinations[1];
unset($destinations[1]);
array_unshift($destinations, $default);
return $destinations;
}
//
// Get destination name
//
function fn_get_destination_name($destination_id, $lang_code = CART_LANGUAGE)
{
if (!empty($destination_id)) {
  return db_get_field("SELECT destination FROM ?:destination_descriptions WHERE destination_id = ?i AND lang_code = ?s", $destination_id, $lang_code);
}
return false;
}
//
// Helper for fn_get_available_destination function
//
// @$partial - check for partial equality
//
function fn_check_element($elms, $elm, $partial = false)
{
if (empty($elm)) {
  return false;
}
$suitable = false;
foreach ($elms as $k => $v) {
  if ($partial == true) {
   $__tmp = str_replace(array('*', '?', '/'), array('.*', '.', '\/'), $v);
   if (preg_match("/^$__tmp\$/iu", $elm)) {
	$suitable = true;
	break;
   }
  } else {
   if ($v == $elm) {
	$suitable = true;
	break;
   }
  }
}
return $suitable;
}
//
// Return most coincedence available destination by the following parameters...
//
function fn_get_available_destination($location)
{
$country = !empty($location['country']) ? $location['country'] : '';
$state = !empty($location['state']) ? $location['state'] : '';
$zipcode = !empty($location['zipcode']) ? $location['zipcode'] : '';
$city = !empty($location['city']) ? $location['city'] : '';
$address = !empty($location['address']) ? $location['address'] : '';
if (!empty($country)) {
  $state_id = fn_get_state_id($state, $country);
  $city_id = fn_get_city_id($city, $state);

  $condition = '';
  if (AREA == 'C') {
   $condition .= fn_get_localizations_condition('localization');
  }
  $__dests = db_get_array("SELECT a.* FROM ?:destination_elements as a LEFT JOIN ?:destinations as b ON b.destination_id = a.destination_id WHERE b.status = 'A' AND (b.destination_id = 1 OR (1 ?p))", $condition);
  $destinations = array();
  foreach ($__dests as $k => $v) {
   $destinations[$v['destination_id']][$v['element_type']][] = $v['element'];
  }
  $concur_destinations = array();
  foreach ($destinations as $dest_id => $elm_types) {
   // Significance level. The more significance level means the most amount of coincidences
   $significance = 0;
   $dest_countries = !empty($elm_types['C']) ? $elm_types['C'] : array();
   $dest_states = !empty($elm_types['S']) ? $elm_types['S'] : array();
   foreach ($elm_types as $elm_type => $elms) {
	// Check country
	if ($elm_type == 'C') {
	 $suitable = fn_check_element($elms, $country);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 1 * (1 / count($elms));
	}
  
	// Check state
	if ($elm_type == 'S') {
	 // if country is in destanation_countries and it haven't got states,
	 // we suppose that destanation cover all country
	 if (!in_array($country, $dest_countries) || fn_get_states($country)) {
	  $suitable = fn_check_element($elms, $state_id);
	  if ($suitable == false) {
	   break;
	  }
	 } else {
	  $suitable = true;
	 }
	 $significance += 2 * (1 / count($elms));
	}
	// Check city
	if ($elm_type == 'T') {
	  if (!in_array($state, $dest_states) || fn_get_cities($state)) {
	 $suitable = fn_check_element($elms, $city_id);
	 if ($suitable == false) {
	  break;
	 }
	  } else {
	   $suitable = true;
	 }
	 $significance += 3 * (1 / count($elms));
	}
	// Check zipcode
	if ($elm_type == 'Z') {
	 $suitable = fn_check_element($elms, $zipcode, true);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 4 * (1 / count($elms));
	}
	// Check address
	if ($elm_type == 'A') {
	 $suitable = fn_check_element($elms, $address, true);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 5 * (1 / count($elms));
	}
   }
   $significance = number_format($significance, 2, '.', '');
   if ($suitable == true) {
	$concur_destinations[$significance][] = $dest_id;
   }
  }
  if (!empty($concur_destinations)) {
   ksort($concur_destinations, SORT_NUMERIC);
   $concur_destinations = array_pop($concur_destinations);
   return reset($concur_destinations);
  } else {
   return false;
  }
}
return false;
}
//
// Return state ID by it's code and country code
//
function fn_get_state_id($state = '', $country = '')
{
static $state_ids;
if (empty($state) || empty($country)) {
  return false;
}
if (empty($state_ids[$country][$state])) {
  $state_ids[$country][$state] = db_get_field("SELECT state_id FROM ?:states WHERE code = ?s AND country_code = ?s", $state, $country);
}
return $state_ids[$country][$state];
}
function fn_get_city_id($city = '', $state = '')
{
static $city_ids;
if (empty($city) || empty($state)) {
  return false;
}
if (empty($city_ids[$state][$city])) {
  $city_ids[$state][$city] = db_get_field("SELECT city_id FROM ?:cities WHERE city_id = ?s AND state_id = ?s", $city, $state);
}
return $state_ids[$state][$city];
}

I also had to insert a line at controllers/customer/checkout.php near //Get countries and states like that:

$view-&gt;assign('cities', fn_get_all_cities());



then I had to declare the 2 rows for b_city and s_city at profile_fields table, with field_type='K' (mine declaration) so I can recognize the new city selectbox at active_skin/customer/views/profiles/components/profile_fields.tpl by inserting something like that:

{elseif $field.field_type == "K"}  {* City selectbox *}
  <select id="{$id_prefix}elm_{$field.field_id}" class="{if !$skip_field}{$_class}{/if}" name="{$data_name}[{$data_id}]" {if !$skip_field}{$disabled_param}{/if}>
   <option value="">- {$lang.select_city} -</option>
   {* Initializing default cities *}
   {assign var="country_code" value=$settings.General.default_country}
   {assign var="state_code" value=$value|default:$settings.General.default_state}
		    {assign var="city_code" value=$value|default:$settings.General.default_city}
   {if $cities}
    {foreach from=$cities.$state_id item=city}
	 <option {if $city_code == $city.city_id}selected="selected"{/if} value="{$city.city_id}">{$city.code}</option>
    {/foreach}
   {/if}
  </select><input type="text" id="elm_{$field.field_id}_d" name="{$data_name}[{$data_id}]" size="32" maxlength="64" value="{$value}" disabled="disabled" class="input-text hidden {if $_class}disabled{/if}"/>
  <input type="hidden" id="{$id_prefix}elm_{$field.field_id}_default" value="{$state_code}" />


Unfortunately cities cannot be initialised !!

 
  • ooaykac
  • Senior Member
  • Members
  • Join Date: 22-Nov 12
  • 275 posts

Posted 17 May 2015 - 11:17 AM #7

I think you should manage /js/tygh/core.js file too.

 
  • stasok
  • Advanced Member
  • Members
  • Join Date: 12-Mar 12
  • 67 posts

Posted 15 April 2018 - 03:02 PM #8

That's very interesting.

I did some experiments according to tbirnseth's usefull thoughts.

The target is to alter city input field to select box dependent to state selection.

But does the locations' functionality about cities wildcards remain the same ?? Because the final target is, on city selection to calculate the shipping cost of an order at checkout step,

So I created a table like this
 

DROP TABLE IF EXISTS `katoikia`.`cscart_cities`;
CREATE TABLE  `katoikia`.`cscart_cities` (
  `city_id` mediumint(<img src='http://forum.cs-cart.com/public/style_emoticons/<#EMO_DIR#>/icon_cool.gif' class='bbc_emoticon' alt='8)' /> unsigned NOT NULL auto_increment,
  `country_code` varchar(2) NOT NULL default '',
  `code` varchar(32) NOT NULL default '',
  `state_id` varchar(32) NOT NULL,
  `status` char(1) NOT NULL default 'A',
  PRIMARY KEY  (`city_id`),
  UNIQUE KEY `cs` (`country_code`,`code`),
  KEY `code` (`code`),
  KEY `country_code` (`country_code`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
then I added functions for bulding and seeking cities, almost like every state function at core/fn.locations.php like that:

//
// Get countries list
//
function fn_get_countries($lang_code = CART_LANGUAGE, $only_avail = false, $paginate = false)
{
$only_avail = ($only_avail == true) ? " WHERE a.status = 'A'" : '';
$limit = '';
$page = empty($_REQUEST['page']) ? 1 : $_REQUEST['page'];
if ($paginate == true) {
  $country_count = db_get_field("SELECT count(*) FROM ?:countries");
  $limit = fn_paginate($page, $country_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.code, a.code_A3, a.code_N3, a.status, a.region, b.country FROM ?:countries as a LEFT JOIN ?:country_descriptions as b ON b.code = a.code AND b.lang_code = ?s $only_avail ORDER BY b.country $limit", $lang_code);
}
//
// Get countries simple list
//
function fn_get_simple_countries($avail_only = false, $lang_code = CART_LANGUAGE)
{
$avail_cond = ($avail_only == true)  ? "WHERE a.status = 'A'" : '';
return db_get_hash_single_array("SELECT a.code, b.country FROM ?:countries as a LEFT JOIN ?:country_descriptions as b ON b.code = a.code AND b.lang_code = ?s $avail_cond ORDER BY b.country", array('code', 'country'), $lang_code);
}
//
// Get states list for specific country
//
function fn_get_states($country = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($country)) {
  return '';
}
$limit = '';
if ($paginate == true) {
  $state_count = db_get_field("SELECT COUNT(*) FROM ?:states WHERE country_code = ?s", $country);
  $limit = fn_paginate(@$_REQUEST['page'], $state_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.state_id, a.country_code, a.code, a.status, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s WHERE a.country_code = ?s ORDER BY b.state $limit", $lang_code, $country);
}
//
// Get cities list for specific state
//
function fn_get_cities($state = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($state)) {
  return '';
}
$limit = '';
if ($paginate == true) {
  $city_count = db_get_field("SELECT COUNT(*) FROM ?:cities WHERE state_id = ?s", $state);
  $limit = fn_paginate(@$_REQUEST['page'], $city_count, Registry::get('settings.Appearance.admin_elements_per_page'));
}
return db_get_array("SELECT a.city_id, a.country_code, a.code, a.state_id, a.status
FROM ?:cities as a WHERE a.country_code = ?s AND a.state_id = ?s ORDER BY a.code $limit", $country, $state);
}

//
// Get states key-value list
//
function fn_get_simple_states($country = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($country)) {
  $country = 'US'; //!!! FIXME: what is the logic should be?
}
return db_get_hash_single_array("SELECT a.code, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s WHERE a.country_code = ?s ORDER BY b.state", array('code', 'state'), $lang_code, $country);
}
//
// Get cities key-value list
//
function fn_get_simple_cities($state = '', $lang_code = CART_LANGUAGE, $paginate = false)
{
if (empty($state)) {
  $state = ''; //!!! FIXME: what is the logic should be?
}
return db_get_hash_single_array("SELECT a.city_id, a.code FROM ?:cities as a WHERE a.state_id = ?s ORDER BY a.code", array('city_id', 'code'), $state);
}
//
// Get states list for specific country
//
function fn_get_all_states($lang_code = CART_LANGUAGE, $extended = false, $avail_only = true)
{
$avail_cond = ($avail_only == true) ? " WHERE a.status = 'A' " : '';
if ($extended == true) {
  return db_get_array("SELECT a.state_id, a.code, b.state, c.country FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s LEFT JOIN ?:country_descriptions as c ON c.code = a.country_code AND c.lang_code = ?s $avail_cond ORDER BY a.country_code, b.state", $lang_code, $lang_code);
} else {
  return db_get_hash_multi_array("SELECT a.country_code, a.code, b.state FROM ?:states as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s $avail_cond ORDER BY a.country_code, b.state", array('country_code'), $lang_code);
}
}
//
// Get cities list for specific state
//
function fn_get_all_cities($lang_code = CART_LANGUAGE, $extended = false, $avail_only = true)
{
$avail_cond = ($avail_only == true) ? " WHERE a.status = 'A' " : '';
if ($extended == true) {
  return db_get_array("SELECT a.city_id, a.code, a.state_id, b.state, c.country FROM ?:cities as a LEFT JOIN ?:state_descriptions as b ON b.state_id = a.state_id AND b.lang_code = ?s LEFT JOIN ?:country_descriptions as c ON c.code = a.country_code AND c.lang_code = ?s ORDER BY a.country_code, b.state", $lang_code, $lang_code);
} else {
  return db_get_hash_multi_array("SELECT a.country_code, a.state_id, a.city_id, a.code FROM ?:cities as a ORDER BY a.country_code, a.code", array('state_id'), $lang_code);
}
}

// Get state name (results are cached)
function fn_get_state_name($state_code, $country_code, $lang_code = CART_LANGUAGE)
{
static $states = array();
if (!isset($states[$country_code][$state_code])) {
  $states[$country_code][$state_code] = db_get_field("SELECT ?:state_descriptions.state FROM ?:states LEFT JOIN ?:state_descriptions ON ?:state_descriptions.state_id = ?:states.state_id AND ?:state_descriptions.lang_code = ?s WHERE ?:states.country_code = ?s AND ?:states.code = ?s", $lang_code, $country_code, $state_code);
}
return $states[$country_code][$state_code];
}
// Get city name (results are cached)
function fn_get_city_name($state_id, $country_code)
{
static $cities = array();
if (!isset($cities[$country_code][$state_id])) {
  $cities[$country_code][$state_id] = db_get_field("SELECT ?:cities.code FROM ?:cities WHERE ?:cities.country_code = ?s AND ?:cities.state_id = ?s", $country_code, $state_id);
}
return $cities[$country_code][$state_id];
}

// Get country name (results are cached)
function fn_get_country_name($country_code, $lang_code = CART_LANGUAGE)
{
static $countries = array();
if (empty($countries[$country_code])) {
  $countries[$country_code] = db_get_field("SELECT country FROM ?:country_descriptions WHERE code = ?s AND lang_code = ?s", $country_code, $lang_code);
}

return $countries[$country_code];
}
// Get countries name (results are cached)
function fn_get_countries_name($country_codes, $lang_code = CART_LANGUAGE)
{
$countries = db_get_hash_array("SELECT country, code FROM ?:country_descriptions WHERE code IN (?a) AND lang_code = ?s", 'code', $country_codes, $lang_code);
return $countries;
}
//
// Get all destinations list
//
function fn_get_destinations($lang_code = CART_LANGUAGE)
{
$destinations = db_get_hash_array("SELECT a.destination_id, a.status, a.localization, b.destination FROM ?:destinations as a LEFT JOIN ?:destination_descriptions as b ON a.destination_id = b.destination_id AND b.lang_code = ?s ORDER BY destination", 'destination_id', $lang_code);
$default = $destinations[1];
unset($destinations[1]);
array_unshift($destinations, $default);
return $destinations;
}
//
// Get destination name
//
function fn_get_destination_name($destination_id, $lang_code = CART_LANGUAGE)
{
if (!empty($destination_id)) {
  return db_get_field("SELECT destination FROM ?:destination_descriptions WHERE destination_id = ?i AND lang_code = ?s", $destination_id, $lang_code);
}
return false;
}
//
// Helper for fn_get_available_destination function
//
// @$partial - check for partial equality
//
function fn_check_element($elms, $elm, $partial = false)
{
if (empty($elm)) {
  return false;
}
$suitable = false;
foreach ($elms as $k => $v) {
  if ($partial == true) {
   $__tmp = str_replace(array('*', '?', '/'), array('.*', '.', '\/'), $v);
   if (preg_match("/^$__tmp\$/iu", $elm)) {
	$suitable = true;
	break;
   }
  } else {
   if ($v == $elm) {
	$suitable = true;
	break;
   }
  }
}
return $suitable;
}
//
// Return most coincedence available destination by the following parameters...
//
function fn_get_available_destination($location)
{
$country = !empty($location['country']) ? $location['country'] : '';
$state = !empty($location['state']) ? $location['state'] : '';
$zipcode = !empty($location['zipcode']) ? $location['zipcode'] : '';
$city = !empty($location['city']) ? $location['city'] : '';
$address = !empty($location['address']) ? $location['address'] : '';
if (!empty($country)) {
  $state_id = fn_get_state_id($state, $country);
  $city_id = fn_get_city_id($city, $state);

  $condition = '';
  if (AREA == 'C') {
   $condition .= fn_get_localizations_condition('localization');
  }
  $__dests = db_get_array("SELECT a.* FROM ?:destination_elements as a LEFT JOIN ?:destinations as b ON b.destination_id = a.destination_id WHERE b.status = 'A' AND (b.destination_id = 1 OR (1 ?p))", $condition);
  $destinations = array();
  foreach ($__dests as $k => $v) {
   $destinations[$v['destination_id']][$v['element_type']][] = $v['element'];
  }
  $concur_destinations = array();
  foreach ($destinations as $dest_id => $elm_types) {
   // Significance level. The more significance level means the most amount of coincidences
   $significance = 0;
   $dest_countries = !empty($elm_types['C']) ? $elm_types['C'] : array();
   $dest_states = !empty($elm_types['S']) ? $elm_types['S'] : array();
   foreach ($elm_types as $elm_type => $elms) {
	// Check country
	if ($elm_type == 'C') {
	 $suitable = fn_check_element($elms, $country);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 1 * (1 / count($elms));
	}
  
	// Check state
	if ($elm_type == 'S') {
	 // if country is in destanation_countries and it haven't got states,
	 // we suppose that destanation cover all country
	 if (!in_array($country, $dest_countries) || fn_get_states($country)) {
	  $suitable = fn_check_element($elms, $state_id);
	  if ($suitable == false) {
	   break;
	  }
	 } else {
	  $suitable = true;
	 }
	 $significance += 2 * (1 / count($elms));
	}
	// Check city
	if ($elm_type == 'T') {
	  if (!in_array($state, $dest_states) || fn_get_cities($state)) {
	 $suitable = fn_check_element($elms, $city_id);
	 if ($suitable == false) {
	  break;
	 }
	  } else {
	   $suitable = true;
	 }
	 $significance += 3 * (1 / count($elms));
	}
	// Check zipcode
	if ($elm_type == 'Z') {
	 $suitable = fn_check_element($elms, $zipcode, true);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 4 * (1 / count($elms));
	}
	// Check address
	if ($elm_type == 'A') {
	 $suitable = fn_check_element($elms, $address, true);
	 if ($suitable == false) {
	  break;
	 }
	 $significance += 5 * (1 / count($elms));
	}
   }
   $significance = number_format($significance, 2, '.', '');
   if ($suitable == true) {
	$concur_destinations[$significance][] = $dest_id;
   }
  }
  if (!empty($concur_destinations)) {
   ksort($concur_destinations, SORT_NUMERIC);
   $concur_destinations = array_pop($concur_destinations);
   return reset($concur_destinations);
  } else {
   return false;
  }
}
return false;
}
//
// Return state ID by it's code and country code
//
function fn_get_state_id($state = '', $country = '')
{
static $state_ids;
if (empty($state) || empty($country)) {
  return false;
}
if (empty($state_ids[$country][$state])) {
  $state_ids[$country][$state] = db_get_field("SELECT state_id FROM ?:states WHERE code = ?s AND country_code = ?s", $state, $country);
}
return $state_ids[$country][$state];
}
function fn_get_city_id($city = '', $state = '')
{
static $city_ids;
if (empty($city) || empty($state)) {
  return false;
}
if (empty($city_ids[$state][$city])) {
  $city_ids[$state][$city] = db_get_field("SELECT city_id FROM ?:cities WHERE city_id = ?s AND state_id = ?s", $city, $state);
}
return $state_ids[$state][$city];
}
I also had to insert a line at controllers/customer/checkout.php near //Get countries and states like that:

$view-&gt;assign('cities', fn_get_all_cities());



then I had to declare the 2 rows for b_city and s_city at profile_fields table, with field_type='K' (mine declaration) so I can recognize the new city selectbox at active_skin/customer/views/profiles/components/profile_fields.tpl by inserting something like that:

{elseif $field.field_type == "K"}  {* City selectbox *}
  <select id="{$id_prefix}elm_{$field.field_id}" class="{if !$skip_field}{$_class}{/if}" name="{$data_name}[{$data_id}]" {if !$skip_field}{$disabled_param}{/if}>
   <option value="">- {$lang.select_city} -</option>
   {* Initializing default cities *}
   {assign var="country_code" value=$settings.General.default_country}
   {assign var="state_code" value=$value|default:$settings.General.default_state}
		    {assign var="city_code" value=$value|default:$settings.General.default_city}
   {if $cities}
    {foreach from=$cities.$state_id item=city}
	 <option {if $city_code == $city.city_id}selected="selected"{/if} value="{$city.city_id}">{$city.code}</option>
    {/foreach}
   {/if}
  </select><input type="text" id="elm_{$field.field_id}_d" name="{$data_name}[{$data_id}]" size="32" maxlength="64" value="{$value}" disabled="disabled" class="input-text hidden {if $_class}disabled{/if}"/>
  <input type="hidden" id="{$id_prefix}elm_{$field.field_id}_default" value="{$state_code}" />

Unfortunately cities cannot be initialised !!

 

as i know cities load async ajax.


Best cs cart theme UniTheme and YoupiTheme!
Want discount? Write me private.
Cs-cart customisation services.

 
  • teosu
  • Senior Member
  • Members
  • Join Date: 09-Oct 14
  • 275 posts

Posted 16 April 2018 - 01:13 PM #9

i build my addon. its work same as like states. bu want edit some core files. core.js and some profile scripts.



 
  • Hungryweb
  • Senior Member
  • Authorized Reseller
  • Join Date: 10-Feb 12
  • 1191 posts

Posted 17 April 2018 - 07:53 AM #10

There is already and add-on created for CS-Cart Russian version called ru_cities, you can get it from there 8) ,

it dosen't have a dropdown for the cities instead they have an autocomplete functionality



 
  • eComLabs
  • CS-Cart Expert
  • Authorized Reseller
  • Join Date: 27-Jan 14
  • 17267 posts

Posted 17 April 2018 - 01:07 PM #11

There is already and add-on created for CS-Cart Russian version called ru_cities, you can get it from there 8) ,

it dosen't have a dropdown for the cities instead they have an autocomplete functionality

 

I think, CS-Cart license department will have questions, if you just copy and past this addon to international CS-Cart version


GET A FREE QUOTE | CS-Cart Add-ons | CS-Cart Licenses | CS-Cart Development | CS-Cart Design | Server Configuration | UniTheme and YOUPI
CS-Cart                USD 345     Multi-Vendor              USD 1250    CS-Cart RU                         24500 руб.
CS-Cart Ultimate  USD 775     CS-Cart + YOUPI      USD 545      CS-Cart RU + UniTheme    36000 руб.


 
  • lorenzo
  • Member
  • Trial users
  • Join Date: 20-Dec 17
  • 39 posts

Posted 19 April 2018 - 02:20 PM #12

There is already and add-on created for CS-Cart Russian version called ru_cities, you can get it from there 8) ,

it dosen't have a dropdown for the cities instead they have an autocomplete functionality

Hi sorry to use this unhortodox way... @hungryweb you have PVT and  Tickets ..pls