1

您好,我有这个聪明的代码,可以生成按州 ISO 代码排序的确定国家/地区的州列表

countries = new Array();
{foreach from=$countries item='country'}
    {if isset($country.states)}
        countries[{$country.id_country|intval}] = new Array();
        {foreach from=$country.states item='state' name='states'}
            countries[{$country.id_country|intval}]['{$state.id_state|intval}'] = '{$state.name|escape:'htmlall':'UTF-8'}';
        {/foreach}
    {/if}
{/foreach}

结果就是这样,对我来说没问题,因为是按 ISO CODE 订购的

countries = new Array();
countries[10] = new Array();
countries[10]['53'] = 'AG';
countries[10]['54'] = 'AL';
countries[10]['55'] = 'AN';
countries[10]['56'] = 'AO';
countries[10]['58'] = 'AP';
countries[10]['93'] = 'AQ';
countries[10]['57'] = 'AR';
countries[10]['59'] = 'AT';
countries[10]['60'] = 'AV';
countries[10]['61'] = 'BA';
countries[10]['64'] = 'BG';
countries[10]['65'] = 'BI';
countries[10]['62'] = 'BL';
countries[10]['63'] = 'BN';
countries[10]['66'] = 'BO';
countries[10]['69'] = 'BR';
countries[10]['68'] = 'BS';
countries[10]['162'] = 'BT';
countries[10]['67'] = 'BZ';
countries[10]['70'] = 'CA';
countries[10]['72'] = 'CB';
countries[10]['73'] = 'CE';
countries[10]['76'] = 'CH';
countries[10]['156'] = 'CI';
countries[10]['71'] = 'CL';
countries[10]['81'] = 'CN';
countries[10]['77'] = 'CO';
countries[10]['79'] = 'CR';
countries[10]['78'] = 'CS';
countries[10]['74'] = 'CT';
countries[10]['75'] = 'CZ';
countries[10]['82'] = 'EN';

在同一页面中,我有这个 javascript 填充选择 html 标记,但按 ID 而非 ISO CODE 订购选项标签,我不知道为什么

$(document).ready(function(){
    $('select#id_country').change(function(){
        updateState();
    });
    updateState();
});

function updateState()
{
    $('select#id_state option:not(:first-child)').remove();
        var states = countries[$('select#id_country').val()];
        if( typeof(states) != 'undefined' )
        {
            for (indexState in states)
            {
                //ie bug fix
                if (indexState != 'indexOf')
                    $('select#id_state').append('<option value="'+indexState+'"'+ (idSelectedCountry == indexState ? ' selected="selected' : '') + '">'+states[indexState]+'</option>');
            }
            $('p.id_state:hidden').slideDown('slow');
        }
        else
            $('p.id_state').slideUp('fast');
}
4

1 回答 1

0

问题是您的 ISO CODES 对象就像一个数组而不是一个对象。当您将项目添加到具有数字索引的数组时,它会自动将其按特定顺序放置在该数组中,这就是数组在 javascript 中的工作方式。
例如,如果您在 Chrome 的控制台中尝试此代码:

var arr = [];
arr[4] = "data"; //same for arr['4'] - javascript will convert it to arr[4]
arr;

它将向您显示以下结果:

[undefined × 4, "data"]

这意味着它将创建所有 5 个索引(从 0 到 4),当前 4 个未定义时,第五个(索引 4)将是您设置的值。
现在,如果您要添加另一个低于 4 的索引,比如说arr[2] = "Z Data";,现在数组将是:

[undefined × 2, "Z Data", undefined × 1, "data"]

如您现在所见,按自然数组方式排序的值(无论内容和插入顺序如何)。

在您的情况下,如果您希望它被订购,有几个选项可以完成它:
1 - 最好的选择是创建一个包含数据对象的有序数组:

var countries = new Array();
{foreach from=$countries item='country'}
    {if isset($country.states)}
        countries[{$country.id_country|intval}] = new Array();
        {foreach from=$country.states item='state' name='states'}
            countries[{$country.id_country|intval}].push({state_id: {$state.id_state|intval}, iso: '{$state.name|escape:'htmlall':'UTF-8'}'});
        {/foreach}
    {/if}
{/foreach}

这将被编译成:

var countries = new Array();
countries[10] = new Array();
countries[10].push({id: 53, iso:'AG'});
countries[10].push({id: 54, iso:'AL'});
countries[10].push({id: 55, iso:'AN'});
countries[10].push({id: 56, iso:'AO'});
countries[10].push({id: 58, iso:'AP'});
countries[10].push({id: 93, iso:'AQ'});
countries[10].push({id: 57, iso:'AR'});
countries[10].push({id: 59, iso:'AT'});
countries[10].push({id: 60, iso:'AV'});
//etc...

2 - 另一种选择是通过在数组的索引前加上字符串来将数组转换为对象:

var countries = new Array();
{foreach from=$countries item='country'}
    {if isset($country.states)}
        countries[{$country.id_country|intval}] = {}; //object initialization
        {foreach from=$country.states item='state' name='states'}
            countries[{$country.id_country|intval}]['s{$state.id_state|intval}'] = '{$state.name|escape:'htmlall':'UTF-8'}';
        {/foreach}
    {/if}
{/foreach}

这将被编译成:

var countries = new Array();
countries[10] = {};
countries[10]['s53'] = 'AG';
countries[10]['s54'] = 'AL';
countries[10]['s55'] = 'AN';
countries[10]['s56'] = 'AO';
countries[10]['s58'] = 'AP';
countries[10]['s93'] = 'AQ';
countries[10]['s57'] = 'AR';
countries[10]['s59'] = 'AT';
countries[10]['s60'] = 'AV';
//ect...

一旦您将它用作对象,它将按照您设置的顺序对列表进行排序。

3 - 这个选项也是关于将数组转换为对象,但这次用值切换索引:

var countries = new Array();
{foreach from=$countries item='country'}
    {if isset($country.states)}
        countries[{$country.id_country|intval}] = {}; //object initialization
        {foreach from=$country.states item='state' name='states'}
            countries[{$country.id_country|intval}]['{$state.name|escape:'htmlall':'UTF-8'}'] = {$state.id_state|intval};
        {/foreach}
    {/if}
{/foreach}

这将被编译成:

var countries = new Array();
countries[10] = {};
countries[10]['AG'] = 53;
countries[10]['AL'] = 54;
countries[10]['AN'] = 55;
countries[10]['AO'] = 56;
countries[10]['AP'] = 58;
countries[10]['AQ'] = 93;
countries[10]['AR'] = 57;
countries[10]['AT'] = 59;
countries[10]['AV'] = 60;
//ect...

4 - 当然,最好的选择是将有序对象(如选项 1 中所述)编码为服务器端 (PHP) 上的 JSON,并在客户端 (JavaScript) 上对其进行解码,但修复它需要更多时间.

希望它有所帮助,并且您了解 JavaScript 中数组的行为。

祝你好运!

于 2013-11-03T10:16:57.903 回答