1

我正在设计一个表单构建界面。所有可用字段将位于界面左侧的无序列表中,右侧有一个大的空无序列表,它将成为我的网络表单。使该界面工作的“技巧”是通过将 html 附加到可放置的 ui 元素中,将左侧的列表项转换为有效的 html 元素,然后再将它们附加到右侧的可排序列表中。

我让它工作......主要......使用draggable()和sortable()。目前,我使用 sortable 的接收事件从可拖动元素中获取 id,我将其放入 data() 块中以传递给更新事件。从那里,我使用 id 元素进行 ajax 调用,确定它是什么类型的字段以及应该从后端添加哪些选项,构建元素,然后使用 将其放入接口中ui.item.html,这是由更新功能。

我的方法的问题是它在拖动元素时也会触发,这会导致选择元素在无意中附加到可排序列表时在屏幕上乱扔垃圾。显然,接收事件是仅在排序从连接列表中获取项目时触发的事件。但是,如果我尝试对ui.item元素进行内部 html,它会更改源列表,而不是所需的目标。当项目已经在右侧的网络表单列表中时,如果它们只是被排序,我绝对不想修改它们。

有什么方法可以访问和更改连接sortable()列表接收事件中的目标 html?还有其他策略可以解决我的挑战吗?

编码:

<div class="grid_3 mainwindow formfields">

    <h3>Available Fields</h3>
    <div id="accordion">
         <ul>
            <li>First Name</li>
            <li>Last Name</li>  
            <li>Company</li>            
         </ul>
    </div>

    </div>
    </div> 

    <div class="grid_12 formcontainer formfields">
    <h3>Webform</h3>
    <form id="form" action="http://responses.smarttracks.com" method="post">
         <input type="hidden" name="webform_id" id="webform_id" value="<?php echo $webform_id ?>"></input>

         <ul id="webform_list"></ul>
    </form>
    </div>

和 jQuery

/*****  Make webform fields draggable   *****/
    $( ".master_list li" ).draggable({
        connectToSortable: "#webform_list",
        helper: "clone",
        revert: "invalid"
    });

/*****  Make form elements sortable *****/
    $( "#webform_list" ).sortable({
        revert: true,
        cursor: 'pointer',
        placeholder: "placeholderdiv",
        receive: function(event, ui) {
            $(this).data('id', ui.item[0].id);
            var element = event.target


        },

        update: function(event, ui) {
            var fieldname = ui.item.text();
            if ($(this).data('id')) {

                $.ajax({
                    url: "/webform/getFieldAttributes",                 
                    timeout: 30000,
                    type: "POST",
                    data: 'id='+$(this).data('id'),
                    dataType: 'json',
                    error: function(XMLHttpRequest, textStatus, errorThrown)  {
                         alert("An error has occurred making the request: " + errorThrown)
                    },
                    success: function(data){
                        switch (data.control_type) {
                            case 'text':
                                var inputfield = $('<input type="text">').attr('id', 'fieldname');

                                var field = (ui.item).text();

                                switch (field) {
                                    case 'Email Address':
                                        inputfield.addClass('validate[optional,custom[email]]');
                                        break;
                                    default:
                                        inputfield.addClass('validate[required]');
                                        break;
                                }

                                break;
                            case 'textarea': 
                                var inputfield = $('<textarea>');
                                break;
                            case 'Dropdown Menu (Single Select)':
                                var inputfield = $('<select>');

                                $.each(data.field_options, function(name, value) {
                                    inputfield.append($("<option></option>").attr("value",name).text(value)) 
                                });

                                inputfield.addClass('validate[required]');
                                break;
                            case 'Radio Buttons (Single Select)':

                                var inputfield = $('<div class="webform_radiogroup">');

                                $.each(data.field_options, function(name, value) {
                                    var container = $('<div class="webform_radio_option">');
                                    var radio = $('<input type="radio">').attr({    name: name,value: value,id: name });
                                    radio.appendTo(container);
                                    $('<label for="'+name+'">'+name+'</label>').appendTo(container);
                                    $('<div class="clear">').appendTo(container);

                                    container.appendTo(inputfield);
                                });
                                break;
                        }

                        if (data.control_type == 'Radio Buttons (Single Select)') {
                            ui.item.html('<div class="webform_radiogroup_label">'+fieldname+'</div>').append(inputfield).append('<div class="clear">').wrapInner('<div class="webform_questiongroup">').wrapInner('<div class="hoverdiv" />');
                        } else {
                            ui.item.html('').append('<label for="'+fieldname+'">'+fieldname+'</label>').append(inputfield).wrapInner('<div class="hoverdiv" />');
                        }

                    }
                });
            }
        }   
    });
4

2 回答 2

6

而是像这样使用 droppable

    $( ".master_list li" ).draggable({
      connectToSortable: "#webform_list",
      helper: "clone",
      revert: "invalid"
   });
    $( "#webform_list" ).droppable({
        drop: function( event, ui ) {
           // your ajax code
        }
    }).sortable({
       handle : 'p',
       cursor : 'crosshair'
   });

我没有发布完整的代码,只是给了你大致的工作思路。

于 2012-11-10T06:07:21.743 回答
3

您根本不需要使用接收方法。您可以使用 update 方法访问对象$(ui.item)

只需将您的代码更改为:

    placeholder: "placeholderdiv",
    // removed receive method

    update: function(event, ui) {

        var draggingElement = $(ui.item);
        var fieldname = draggingElement.text();
        var fieldId = draggingElement.attr('id'); // or whatever you require.

        if (fieldId) {
           // etc...

至于您的事件触发两次的问题,我试图复制这是JsFiddle但我无法将您的代码添加到小提琴中吗?

谢谢。

于 2012-11-08T00:57:29.127 回答