`

一个基于jQuery的可重用的无限制级别联动Select。

阅读更多
这标题起得好长好牛B,喔呵呵呵呵……

忙活一下午,写出这么个玩意,其中emptySelect和loadSelect方法的代码来自《jQuery in Action》一书,稍有改动。childSelect是自己照着加的,可能写得不太好看。

(function($){$.fn.loadSelect = function(optionsDataArray){
    return this.each(function(){
        if(this.tagName == 'SELECT'){
            var selectElement = this;
            $.each(optionsDataArray, function(index, optionData){
                selectElement.options.add(new Option(optionData.text, optionData.value));
            });
            var defaultOption = new Option('\u8bf7\u9009\u62e9', '');
            defaultOption.selected = true;
            selectElement.options.add(defaultOption);
        }
    });
};

$.fn.childSelect = function(selector, makeURL){
    var elem = this[0];
    if(selector === undefined){
        return elem.child ? this.pushStack(elem.child) : undefined;
    }

    elem.child = $(selector)[0];
    this.change(function(event){
        var childSelect = $(this).childSelect();
        childSelect.emptySelect();
        if($(this).val()){
            childSelect.attr('disabled', false);
            $.getJSON(makeURL.apply($(this)), function(data){
                childSelect.loadSelect(data).change();
            });
        }else{
            childSelect.attr('disabled', true);
        }
        if(childSelect.childSelect()) childSelect.change();
    });
    return this.pushStack(elem.child);
};

$.fn.emptySelect = function(){
    return this.each(function(){
        if(this.tagName == 'SELECT')
            this.options.length = 0;
    });
};})(jQuery);


这里解释一下childSelect的用法:
这个方法是用来给一个select元素设置子级select元素的,一旦设置了子级select元素,父select元素的change事件触发时将通过$.getJSON向服务器发送一个请求,并将返回的json填充到子级select元素中。如果想让父select元素的某一项选中时不发送请求,只要将这一项的value设置成空字符串''即可:如
<select><option value=''>请选择</option></select>

参数selector用来选择子select元素,跟$(selector)的用法一样。
makeURL必须是一个方法,这个方法用于创建要请求的url,上下文(即this)为父select元素的包装集对象(即jQuery包装后的父select元素)。
这个方法类似于val()方法——省略参数的时候是用于获取子select元素的包装集。
这个版本的代码对服务端返回的JSON的格式有一些要求,返回的JSON数组必须是这种格式:
[{text:'一年1班', value:'1'},{text:'一年2班', value:'2'}]


使用方法如下:
$('#grade').childSelect('#class', function(){return 'grades/'+this.val()+'/classes'}).end().change()

也可以链式地继续往后面添加子select元素的子select元素,或者直接给子select元素添加事件。

接着我遇到了一些问题。rails的to_json生成的json格式一般是这样的
[{class_name1:{attr1.1:value1.1,attr1.2:value1.2}},{class_name2:{attr2.1:value2.1,attr2.2:value2.2}}]
,没什么规律的,或者说规律比较复杂,要给select元素填充不同的ruby类数组的话,就必须知道这个ruby类的类名、用来做text和value的属性名。
我修改了一下loadSelect和childSelect方法,如下:
(function($){$.fn.loadSelect = function(optionsDataArray, hash){
    return this.each(function(){
        if(this.tagName == 'SELECT'){
            var selectElement = this;
            $.each(optionsDataArray, function(index, optionData){
                selectElement.options.add(new Option(optionData[hash.className][hash.text], optionData[hash.className][hash.value]));
            var defaultOption = new Option('\u8bf7\u9009\u62e9', '');
            defaultOption.selected = true;
            selectElement.options.add(defaultOption);
            });
        }
    });
};

$.fn.childSelect = function(selector, makeURL, hash){
    var elem = this[0];
    if(selector === undefined){
        return elem.child ? this.pushStack(elem.child) : undefined;
    }

    elem.child = $(selector)[0];
    this.change(function(event){
        var childSelect = $(this).childSelect();
        childSelect.emptySelect();
        if($(this).val()){
            childSelect.attr('disabled', false);
            $.getJSON(makeURL.apply($(this)), function(data){
                childSelect.loadSelect(data, hash).change();
            });
        }else{
            childSelect.attr('disabled', true);
        }
        if(childSelect.childSelect()) childSelect.change();
    });
    return this.pushStack(elem.child);
};})(jQuery);

就是给方法添加了一个hash(或者说对象)作为参数,让客户端代码来指定ruby类的类名、用于text和value的属性名,使用的时候就是多传一个hash,像这样:
$('#grade').childSelect('#clazz', function(){return 'grades/'+this.val()+'/classes'}, {className:'clazz', value:'id', text:'class_no'}).end().change();


还有另外一种解决方法,就是给rails的每个对象添加一个json_for_select方法,生成这种格式的JSON:
[{text:'一年1班', value:'1'},{text:'一年2班', value:'2'}]
,这样就可以免去上面多出来的那个hash。

问题是……json_for_select该怎么写,我还没有头绪……似乎要同时去修改ActiveSuppor::JSON和Object。

===========================================================
改好了,在config/initializers下添加一个extension.rb,内容:
class Object
  def json_for_select(hash)
    json = to_json(:only => [hash[:text], hash[:value]])
    json = json.gsub(Regexp.new("\"#{hash[:text]}\":"), "\"text\":").gsub(Regexp.new("\"#{hash[:value]}\":"), "\"value\":")
    json = json.gsub(/\{"\w+":\s\{/, '{').gsub(/\}\}/, '}') if ActiveRecord::Base.include_root_in_json
    json
  end
end

解释:rails启动的时候会自动加载config/initializers下的文件并执行。ActiveRecord::Base.include_root_in_json如果为true,to_json生成的JSON带有类名,如果为false,则不带类名。最后把controller中的
format.html { render :json => @classes.to_json }
换成
format.html { render :json => @classes.json_for_select(:text =>'class_no', :value=>'id')
即可。
分享到:
评论
2 楼 Hooopo 2009-10-14  
or:
format.html { render :text => @classes.to_json }
1 楼 Hooopo 2009-10-14  
format.html { render :json => @classes.to_json }

可以这样
format.html { render :json => @classes }

相关推荐

    基于jquery的N级下拉联动

    在网页开发中,下拉联动(Dropdown Cascade)是一种常见的交互设计,它允许用户通过选择一个选项来触发其他关联下拉菜单的更新。这种效果在层级关系明显的数据展示中非常实用,比如地区选择、产品分类等。本文将深入...

    jquery省市区三级联动下拉菜单_select三级联动下拉菜单

    jquery省市区三级联动下拉菜单_select三级联动下拉菜单 jquery省市区三级联动下拉菜单_select三级联动下拉菜单 jquery省市区三级联动下拉菜单_select三级联动下拉菜单 jquery省市区三级联动下拉菜单_select三级联动...

    基于jQuery+JSON的省市联动效果

    首先,jQuery是一个轻量级的JavaScript库,它简化了DOM操作、事件处理、动画和Ajax交互。在本案例中,jQuery将被用来监听省份选择的变化,并根据变化动态更新城市列表。 JSON(JavaScript Object Notation)是一种...

    jQuery模拟select下拉框三级城市联动代码.zip

    可以包含多个`&lt;option&gt;`元素,每个`&lt;option&gt;`代表一个可选项。在本例中,我们可能会看到三个select元素,分别代表省份、城市和区县,它们将通过JavaScript进行联动。 2. **jQuery事件绑定**:jQuery提供了`$...

    jQuery基于citypicker四级联动菜单选择器代码.zip

    本资源"jQuery基于citypicker四级联动菜单选择器代码.zip"提供了一个实现城市选择器功能的jQuery插件,适用于网页表单,尤其是需要用户输入详细地址的场景。 首先,我们来理解一下什么是四级联动菜单。在网页设计中...

    jquery实现select互斥联动

    3. 互斥联动:互斥联动是指当用户在一个下拉列表中选择一个选项时,其他关联的下拉列表会根据预设规则更新其可选项,通常用于限制用户的选择范围,保证数据的正确性。 二、实现步骤 1. HTML结构:首先,需要创建三...

    jquery cxselect联动插件select多级联动下拉菜单

    jquery cxselect联动插件select多级联动下拉菜单 jquery cxselect联动插件select多级联动下拉菜单 jquery cxselect联动插件select多级联动下拉菜单 jquery cxselect联动插件select多级联动下拉菜单

    基于JQuery地区三级联动列表

    总结来说,"基于JQuery地区三级联动列表"是利用JQuery处理前端动态数据和交互的一个实例,通过监听用户操作,动态获取并填充下级列表,实现一个流畅的地区选择体验。这个过程涉及到的技能点包括JQuery选择器、事件...

    jquery select二级联动菜单

    在网页开发中,jQuery是一个非常流行的JavaScript库,它极大地简化了JavaScript代码的编写,使得DOM操作、事件处理、动画效果等任务变得更加简单。本话题主要关注的是使用jQuery实现的二级联动下拉菜单,这是一种...

    jquery ajax xml 实现select联动

    在Web开发中,jQuery是一个非常流行的JavaScript库,它极大地简化了DOM操作、事件处理和Ajax交互。本示例中,“jquery ajax xml 实现select联动”指的是利用jQuery的Ajax功能从XML文件中获取数据,动态更新HTML中的...

    基于JQUERY的多级联动代码

    首先,`jquery.select.more.js`中的`doselectmore`函数是一个jQuery扩展方法,它接受一个`settings`参数,用于自定义配置。这个方法的核心在于创建和维护一个多级联动的下拉列表。变量`dfop`是默认选项对象,它包含...

    Select2是一个基于jQuery的选择框替代

    Select2是一个基于jQuery的选择框替代。支持搜索、远程数据集和结果分页。

    jquery.selectbox.js select下拉菜单美化代码

    jquery.selectbox.js select下拉菜单美化代码 jquery.selectbox.js select下拉菜单美化代码 jquery.selectbox.js select下拉菜单美化代码

    jquery select2组件

    `Select2`的初始化方法接受一个配置对象,其中包含各种选项,如: ```javascript $('.select2').select2({ placeholder: '请选择...', // 设置占位符文本 allowClear: true, // 是否允许清除选择 ...

    使用js+jquery实现无限极联动

    今天工作需要写树形的联动,于是写了个可扩展的无限极联动下拉选项代码写的比较凌乱 先mark有空再整理 随便截个图!先贴数据库 id category_name 分类名 pid 父分类id orders 排序 1 22223331 0 1 2 2222111 ...

    jquery年月日三级联动

    "jQuery年月日三级联动"是一种常见的交互设计,它通过下拉框的形式,让用户依次选择年、月、日,形成一个完整的日期。这种设计使得日期输入更加直观且易于操作。接下来,我们将深入探讨这个主题。 首先,jQuery是一...

    JQuery三级无刷新联动_select_For C#.

    5. **HTML结构**:每个级别的select应该有一个唯一的ID,方便jQuery选择和操作。例如: ```html &lt;select id="provinceSelect"&gt; &lt;/select&gt; &lt;select id="citySelect"&gt; &lt;/select&gt; &lt;select id="districtSelect"&gt; ...

    jQuery移动端省市二级联动选择插件.zip

    "jQuery移动端省市二级联动选择插件"是专为解决这个问题而设计的一个工具,它利用JavaScript和jQuery库,提供了高效、易用的解决方案。这个插件允许用户在手机或平板设备上方便地选择省份和城市,极大地提升了用户...

    jquery省市区三级联动插件(数据全)

    这个“jquery省市区三级联动插件”是为了解决一个常见的前端开发需求——实现省市区选择的联动效果。这种功能常见于用户注册、地址填写等场景,能够提供用户友好的交互体验。 首先,我们要理解什么是“三级联动”。...

Global site tag (gtag.js) - Google Analytics