I'm using Region & City Manager plug-in to make the City and Region fields as drop down lists and city list depends on region selection because my store is integrated with shipping provider that accepts the city and region only in English while most of my store visitors use another language, That's why I had to make it as drop down to prevent customers from entering the names in other language and get an error.
If the customer added his address from Dashboard-> Address book, all values gets validated and accepted and the customer can place his order without any problems.
If the customer tried to add his address from onepage checkout the city name validation will always fail and customer will not be able to proceed with checkout.
City and Region plugin overrides opcheckout.js and I have compared it with the default script, following is the only change:
shippingRegionUpdater.update();$('shipping:region_id').value=$('billing:region_id').value;$('shipping:region').value=$('billing:region').value;if(shippingCityUpdater){shippingCityUpdater.update();$('shipping:city_id').value=$('billing:city_id').value;$('shipping:city').value=$('billing:city').value;}}else{$('shipping-address-select').value=$('billing-address-select').value;}},setRegionValue:function(){$('shipping:region').value=$('billing:region').value;},save:function(){if(checkout.loadWaiting!=false)return;var validator=new Validation(this.form);if(validator.validate()){checkout.setLoadWaiting('shipping');var request=new Ajax.Request(this.saveUrl,{method:'post',onComplete:this.onComplete,onSuccess:this.onSave,onFailure:checkout.ajaxFailure.bind(checkout),parameters:Form.serialize(this.form)});}},resetLoadWaiting:function(transport){checkout.setLoadWaiting(false);},nextStep:function(transport){if(transport&&transport.responseText){try{response=eval('('+ transport.responseText+')');}
The default value was:
shippingRegionUpdater.update();$('shipping:region_id').value=$('billing:region_id').value;$('shipping:region').value=$('billing:region').value;}else{$('shipping-address-select').value=$('billing-address-select').value;}},setRegionValue:function(){$('shipping:region').value=$('billing:region').value;},save:function(){if(checkout.loadWaiting!=false)return;var validator=new Validation(this.form);if(validator.validate()){checkout.setLoadWaiting('shipping');var request=new Ajax.Request(this.saveUrl,{method:'post',onComplete:this.onComplete,onSuccess:this.onSave,onFailure:checkout.ajaxFailure.bind(checkout),parameters:Form.serialize(this.form)});}},resetLoadWaiting:function(transport){checkout.setLoadWaiting(false);},nextStep:function(transport){if(transport&&transport.responseText){try{response=eval('('+ transport.responseText+')');}
This is billing.phtml:
<form id="co-billing-form" action="">
<?php echo $this->getBlockHtml('formkey') ?>
<fieldset>
<ul class="form-list">
<?php if ($this->customerHasAddresses()): ?>
<li class="wide">
<label for="billing-address-select"><?php echo $this->__('Select a billing address from your address book or enter a new address.') ?></label>
<div class="input-box">
<?php echo $this->getAddressesHtmlSelect('billing') ?>
</div>
</li>
<?php endif; ?>
<li id="billing-new-address-form"<?php if ($this->customerHasAddresses()): ?> style="display:none;"<?php endif; ?>>
<fieldset>
<input type="hidden" name="billing[address_id]" value="<?php echo $this->getAddress()->getId() ?>" id="billing:address_id" />
<ul>
<li class="fields"><?php echo $this->getLayout()->createBlock('customer/widget_name')->setObject($this->getAddress()->getFirstname() ? $this->getAddress() : $this->getQuote()->getCustomer())->setForceUseCustomerRequiredAttributes(!$this->isCustomerLoggedIn())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?></li>
<li class="fields">
<div class="field">
<label for="billing:company"><?php echo $this->__('Company') ?></label>
<div class="input-box">
<input type="text" id="billing:company" name="billing[company]" value="<?php echo $this->escapeHtml($this->getAddress()->getCompany()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Company')) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('company') ?>" />
</div>
</div>
<?php if(!$this->isCustomerLoggedIn()): ?>
<div class="field">
<label for="billing:email" class="required"><em>*</em><?php echo $this->__('Email Address') ?></label>
<div class="input-box">
<input type="text" name="billing[email]" id="billing:email" value="<?php echo $this->escapeHtml($this->getAddress()->getEmail()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Email Address')) ?>" class="input-text validate-email required-entry" />
</div>
</div>
<?php endif; ?>
</li>
<?php $_streetValidationClass = $this->helper('customer/address')->getAttributeValidationClass('street'); ?>
<li class="wide">
<label for="billing:street1" class="required"><em>*</em><?php echo $this->__('Address') ?></label>
<div class="input-box">
<input type="text" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Street Address')) ?>" name="billing[street][]" id="billing:street1" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet(1)) ?>" class="input-text <?php echo $_streetValidationClass ?>" />
</div>
</li>
<?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?>
<?php for ($_i = 2, $_n = $this->helper('customer/address')->getStreetLines(); $_i <= $_n; $_i++): ?>
<li class="wide">
<div class="input-box">
<input type="text" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Street Address %s', $_i)) ?>" name="billing[street][]" id="billing:street<?php echo $_i ?>" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet($_i)) ?>" class="input-text <?php echo $_streetValidationClass ?>" />
</div>
</li>
<?php endfor; ?>
<?php if ($this->helper('customer/address')->isVatAttributeVisible()) : ?>
<li class="wide">
<label for="billing:vat_id"><?php echo $this->__('VAT Number') ?></label>
<div class="input-box">
<input type="text" id="billing:vat_id" name="billing[vat_id]" value="<?php echo $this->escapeHtml($this->getAddress()->getVatId()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('VAT Number')) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('vat_id') ?>" />
</div>
</li>
<?php endif; ?>
<li class="fields">
<div class="field">
<label for="billing:region_id" class="required"><em>*</em><?php echo $this->__('State/Province') ?></label>
<div class="input-box">
<select id="billing:region_id" name="billing[region_id]" title="<?php echo Mage::helper('core')->quoteEscape($this->__('State/Province')) ?>" class="validate-select" style="display:none;">
<option value=""><?php echo $this->__('Please select region, state or province') ?></option>
</select>
<script type="text/javascript">
//<![CDATA[
$('billing:region_id').setAttribute('defaultValue', "<?php echo $this->getAddress()->getRegionId() ?>");
//]]>
</script>
<input type="text" id="billing:region" name="billing[region]" value="<?php echo $this->escapeHtml($this->getAddress()->getRegion()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('State/Province')) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('region') ?>" style="display:none;" />
</div>
</div>
<div class="field">
<label for="billing:city" class="required"><em>*</em><?php echo $this->__('City') ?></label>
<div class="input-box">
<select id="billing:city_id" name="billing[city_id]" title="<?php echo $this->__('City') ?>" class="validate-select" style="display:none;">
<option value=""><?php echo $this->__('Please select City') ?></option>
</select>
<script type="text/javascript">
//<![CDATA[
$('billing:city_id').setAttribute('defaultValue', "<?php echo $this->getAddress()->getCityId() ?>");
//]]>
</script>
<input type="text" title="<?php echo Mage::helper('core')->quoteEscape($this->__('City')) ?>" name="billing[city]" value="<?php echo $this->escapeHtml($this->getAddress()->getCity()) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('city') ?>" id="billing:city" />
</div>
</div>
</li>
<li class="fields">
<div class="field">
<label for="billing:postcode" class="required"><em>*</em><?php echo $this->__('Zip/Postal Code') ?></label>
<div class="input-box">
<input type="text" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Zip/Postal Code')) ?>" name="billing[postcode]" id="billing:postcode" value="<?php echo $this->escapeHtml($this->getAddress()->getPostcode()) ?>" class="input-text validate-zip-international <?php echo $this->helper('customer/address')->getAttributeValidationClass('postcode') ?>" />
</div>
</div>
<div class="field">
<label for="billing:country_id" class="required"><em>*</em><?php echo $this->__('Country') ?></label>
<div class="input-box">
<?php echo $this->getCountryHtmlSelect('billing') ?>
</div>
</div>
</li>
<li class="fields">
<div class="field">
<label for="billing:telephone" class="required"><em>*</em><?php echo $this->__('Telephone') ?></label>
<div class="input-box">
<input type="text" name="billing[telephone]" value="<?php echo $this->escapeHtml($this->getAddress()->getTelephone()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Telephone')) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('telephone') ?>" id="billing:telephone" />
</div>
</div>
<div class="field">
<label for="billing:fax"><?php echo $this->__('Fax') ?></label>
<div class="input-box">
<input type="text" name="billing[fax]" value="<?php echo $this->escapeHtml($this->getAddress()->getFax()) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Fax')) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('fax') ?>" id="billing:fax" />
</div>
</div>
</li>
<?php if(!$this->isCustomerLoggedIn()): ?>
<?php $_dob = $this->getLayout()->createBlock('customer/widget_dob') ?>
<?php $_gender = $this->getLayout()->createBlock('customer/widget_gender') ?>
<?php if ($_dob->isEnabled() || $_gender->isEnabled()): ?>
<li class="fields">
<?php if ($_dob->isEnabled()): ?>
<div class="field">
<?php echo $_dob->setDate($this->getQuote()->getCustomerDob())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
</div>
<?php endif; ?>
<?php if ($_gender->isEnabled()): ?>
<div class="field">
<?php echo $_gender->setGender($this->getQuote()->getCustomerGender())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
</div>
<?php endif ?>
</li>
<?php endif ?>
<?php $_taxvat = $this->getLayout()->createBlock('customer/widget_taxvat') ?>
<?php if ($_taxvat->isEnabled()): ?>
<li>
<?php echo $_taxvat->setTaxvat($this->getQuote()->getCustomerTaxvat())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
</li>
<?php endif ?>
<li class="fields" id="register-customer-password">
<div class="field">
<label for="billing:customer_password" class="required"><em>*</em><?php echo $this->__('Password') ?></label>
<div class="input-box">
<input type="password" name="billing[customer_password]" id="billing:customer_password" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Password')) ?>" class="input-text required-entry validate-password" />
</div>
</div>
<div class="field">
<label for="billing:confirm_password" class="required"><em>*</em><?php echo $this->__('Confirm Password') ?></label>
<div class="input-box">
<input type="password" name="billing[confirm_password]" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Confirm Password')) ?>" id="billing:confirm_password" class="input-text required-entry validate-cpassword" />
</div>
</div>
</li>
<?php endif; ?>
<?php if ($this->isCustomerLoggedIn() && $this->customerHasAddresses()):?>
<li class="control">
<input type="checkbox" name="billing[save_in_address_book]" value="1" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Save in address book')) ?>" id="billing:save_in_address_book" onchange="if(window.shipping) shipping.setSameAsBilling(false);"<?php if ($this->getAddress()->getSaveInAddressBook()):?> checked="checked"<?php endif;?> class="checkbox" /><label for="billing:save_in_address_book"><?php echo $this->__('Save in address book') ?></label>
</li>
<?php else:?>
<li class="no-display"><input type="hidden" name="billing[save_in_address_book]" value="1" /></li>
<?php endif; ?>
<?php echo $this->getChildHtml('form.additional.info'); ?>
</ul>
</fieldset>
</li>
<?php /* Extensions placeholder */ ?>
<?php echo $this->getChildHtml('checkout.onepage.billing.extra')?>
<?php if ($this->canShip()): ?>
<li class="control">
<input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_yes" value="1"<?php if ($this->isUseBillingAddressForShipping()) {?> checked="checked"<?php }?> title="<?php echo Mage::helper('core')->quoteEscape($this->__('Ship to this address')) ?>" onclick="$('shipping:same_as_billing').checked = true;" class="radio" /><label for="billing:use_for_shipping_yes"><?php echo $this->__('Ship to this address') ?></label></li>
<li class="control">
<input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_no" value="0"<?php if (!$this->isUseBillingAddressForShipping()) {?> checked="checked"<?php }?> title="<?php echo Mage::helper('core')->quoteEscape($this->__('Ship to different address')) ?>" onclick="$('shipping:same_as_billing').checked = false;" class="radio" /><label for="billing:use_for_shipping_no"><?php echo $this->__('Ship to different address') ?></label>
</li>
<?php endif; ?>
</ul>
<?php if (!$this->canShip()): ?>
<input type="hidden" name="billing[use_for_shipping]" value="1" />
<?php endif; ?>
<div class="buttons-set" id="billing-buttons-container">
<p class="required"><?php echo $this->__('* Required Fields') ?></p>
<button type="button" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Continue')) ?>" class="button" onclick="billing.save()"><span><span><?php echo $this->__('Continue') ?></span></span></button>
<span class="please-wait" id="billing-please-wait" style="display:none;">
<img src="<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif') ?>" alt="<?php echo Mage::helper('core')->quoteEscape($this->__('Loading next step...')) ?>" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Loading next step...')) ?>" class="v-middle" /> <?php echo $this->__('Loading next step...') ?>
</span>
</div>
</fieldset>
</form>
<script type="text/javascript">
//<![CDATA[
var billing = new Billing('co-billing-form', '<?php echo $this->getUrl('checkout/onepage/getAddress') ?>address/', '<?php echo $this->getUrl('checkout/onepage/saveBilling') ?>');
var billingForm = new VarienForm('co-billing-form');
//billingForm.setElementsRelation('billing:country_id', 'billing:region', '<?php echo $this->getUrl('directory/json/childRegion') ?>', '<?php echo $this->__('Select State/Province...') ?>');
$('billing-address-select') && billing.newAddress(!$('billing-address-select').value);
var billingRegionUpdater = new RegionUpdater('billing:country_id', 'billing:region', 'billing:region_id', <?php echo $this->helper('directory')->getRegionJson() ?>, undefined, 'billing:postcode');
new CityUpdater('billing:country_id', 'billing:region_id', 'billing:city', 'billing:city_id', <?php echo Mage::helper('improvedaddress')->getCityJson() ?>);
//]]>
</script>
Note: I have tried to contact the developer but no luck.