欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

What is the best way to stop Drupal textfield ahah event from disabling field while processing? 重写 Drupal.ahah.prototype.beforeSubmit 自己亲自做的 有大用 有大用

/**
 * Created by Administrator on 2016/12/9.
 */
function trim(str){ //删除左右两端的空格
    return str.replace(/(^\s*)|(\s*$)/g, "");
}
function ltrim(str){ //删除左边的空格
    return str.replace(/(^\s*)/g,"");
}
function rtrim(str){ //删除右边的空格
    return str.replace(/(\s*$)/g,"");
}
$(function(){
    $('#edit-field-pub-task-price-0-value').add('#edit-field-pub-task-num-0-value').keyup(function(){
        var task_price = trim($('#edit-field-pub-task-price-0-value').val());
        var task_num = trim($('#edit-field-pub-task-num-0-value').val());
        task_price =  parseFloat(task_price);
        task_num =  parseInt(task_num);
        if(!isNaN(task_price) && !isNaN(task_num) ){
            $('#edit-field-pub-task-money-0-value').val(task_price * task_num);
        }
        else {
            $('#edit-field-pub-task-money-0-value').val('');
        }
    });
});
var ajaxurl;  //目的是超越 Drupal.ahah.prototype.beforeSubmit
$(document).ready(function() {
    if (typeof beforeSubmitOverride == 'undefined' || beforeSubmitOverride == false) {
    Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
//下面是测试变量
        //console.log('完成了动画');
        //for(var x in form_values){
        //    console.log("form_values start");
        //    console.log(x);
        //    console.log(form_values[x]);
        //    console.log("form_values end");
        //
        //}
        //for(var x in element){
        //    console.log("element start");
        //    console.log(x);
        //    console.log(element[x]);
        //    console.log("element end");
        //}
        //for(var x in options){
        //    console.log("options start");
        //    console.log(x);
        //    console.log(options[x]);
        //    console.log("options end");
        //}
        //这是我附加的
        if(options['url'] == '/delete_accept_task'){
            ajaxurl = '/delete_accept_task';
            if(!(window.confirm("你真的要删除吗?"))){
                return false;
            }
        }

        // Disable the element that received the change.
        $(this.element).addClass('progress-disabled').attr('disabled', true);

        // Insert progressbar or throbber.
        if (this.progress.type == 'bar') {
            var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
            if (this.progress.message) {
                progressBar.setProgress(-1, this.progress.message);
            }
            if (this.progress.url) {
                progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
            }
            this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
            this.progress.object = progressBar;
            $(this.element).after(this.progress.element);
        }
        else if (this.progress.type == 'throbber') {
            this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber">&nbsp;</div></div>');
            if (this.progress.message) {
                $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
            }
            $(this.element).after(this.progress.element);
         }
        };
    };
    beforeSubmitOverride = true;
});
//目的是超越 Drupal.ahah.prototype.success
$(document).ready(function() {
    if (typeof successOverride == 'undefined' || successOverride == false) {
        Drupal.ahah.prototype.success = function (response, status) {
            var wrapper = $(this.wrapper);
            var form = $(this.element).parents('form');
            // Manually insert HTML into the jQuery object, using $() directly crashes
            // Safari with long string lengths. http://dev.jquery.com/ticket/1152
            var new_content = $('<div></div>').html(response.data);

            // Restore the previous action and target to the form.
            form.attr('action', this.form_action);
            this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target');
            this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr');

            // Remove the progress element.
            if (this.progress.element) {
                $(this.progress.element).remove();
            }
            if (this.progress.object) {
                this.progress.object.stopMonitoring();
            }
            $(this.element).removeClass('progress-disabled').attr('disabled', false);

            // Add the new content to the page.
            Drupal.freezeHeight();
            if (this.method == 'replace') {
                wrapper.empty().append(new_content);
            }
            else {
                wrapper[this.method](new_content);
            }

            // Immediately hide the new content if we're using any effects.
            if (this.showEffect != 'show') {
                new_content.hide();
            }

            // Determine what effect use and what content will receive the effect, then
            // show the new content.
            if ($('.ahah-new-content', new_content).size() > 0) {
                $('.ahah-new-content', new_content).hide();
                new_content.show();
                $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed);
            }
            else if (this.showEffect != 'show') {
                new_content[this.showEffect](this.showSpeed);
            }

            // Attach all javascript behaviors to the new content, if it was successfully
            // added to the page, this if statement allows #ahah[wrapper] to be optional.
            if (new_content.parents('html').length > 0) {
                Drupal.attachBehaviors(new_content);
            }

            Drupal.unfreezeHeight();
            //这是我附加的
            if(ajaxurl!=null &&  ajaxurl== '/delete_accept_task'){
                setTimeout(function(){form.css('display','none');},800);
            }
        };
    }
    successOverride = true;
});

I have a simple Drupal form in a custom module where exiting a textfield should retrieve some information about the entered text via ahah to populate a div.

This works fine, except if the user quickly submits the form while the textfield's ahah event is being processed.

It looks like while the ahah event is being processed the textfield is disabled, which of course means it's value is not submitted. This means validation fails as the textfield is a required field, so the user is returned to the form with an appropriate error. The textfield is always empty when this happens.

If the user waits for the event to finish, the textfield returns to being enabled and submitting works as expected, as does submitting by using the enter key while in the textfield (the event doesn't fire then, so the textfield isn't disabled while it retrieves data).

Is there a way to disable the disabling of the textfield while it's ahah event is being processed, or some other workaround?

Example of the textfield:

$form['id'] = array(
    '#type' => 'textfield',
    '#title' => t('Crop No.'),
    '#default_value' => $crop['id'] ? $crop['id'] : '',
    '#size' => 6,
    '#disabled' => $disabled,
    '#ahah' => array(
        'path' => 'spcs-myspuds/yields/js/crop/description/' . $crop_idx,
        'wrapper' => 'spcs-myspuds-yields-edit-crop-description-row-' . $crop_idx,
        'effect' => 'fade',
        'progress' => array(
            'type' => 'none',
        ),
    ),
);

Thanks in advance for any help.

shareimprove this question
 

2 Answers 正确答案

I found a workaround.

I had to override Drupal.ahah.prototype.beforeSubmit, the function that disables the input before the submit (well, duh!).

I included the following JavaScript in my module (using drupal_add_js):

$(document).ready(function() {
  if (typeof beforeSubmitOverride == 'undefined' || beforeSubmitOverride == false) {
    Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
      // Disable the element that received the change.
      // IMiJ: Unless it's a text input, otherwise we could submit while element is diabled and loose data.
      if ($(this.element).attr('type') != 'text') {
        $(this.element).addClass('progress-disabled').attr('disabled', true);
      }

      // Insert progressbar or throbber.
      if (this.progress.type == 'bar') {
        var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
        if (this.progress.message) {
          progressBar.setProgress(-1, this.progress.message);
        }
        if (this.progress.url) {
          progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
        }
        this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
        this.progress.object = progressBar;
        $(this.element).after(this.progress.element);
      }
      else if (this.progress.type == 'throbber') {
        this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber">&nbsp;</div></div>');
        if (this.progress.message) {
          $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
        }
        $(this.element).after(this.progress.element);
      }
    };
  };
  beforeSubmitOverride = true;
});

This is a copy of Drupal.ahah.prototype.beforeSubmit as defined in misc/ahah.js with one small change, wrapping the disabling of the input with an if statement to make sure we don't disable text fields.

This is wrapped in a few lines to ensure the re-defining of the prototype happens just once after the DOM is ready.

It might be better to only stop the disabling of the input if a setting is passed such as "disable" => false, but the above worked for the one case in the one page for the one custom module I needed this fix.

shareimprove this answer
 

You can set the #required property TRUE of the textfield to make it a required field.Please set the #disabled property FALSE to check whether it is not occurred due to this.Please remember that #ahah event will call the validate function when it is being processed.

shareimprove this answer
 
   
Thanks for the answer Naveen, but the references to the #required and #disabled parameters are irrelevant in this case (and #disabled is false in the test scenarios anyway otherwise data couldn't be input that triggers the ahah event). The problem is a an issue with the ahah disabling the input while it processes, and the ahah event does not do any validation or trigger any validation hooks. – ianmjones May 1 '12 at 7:10

I have a simple Drupal form in a custom module where exiting a textfield should retrieve some information about the entered text via ahah to populate a div.

This works fine, except if the user quickly submits the form while the textfield's ahah event is being processed.

It looks like while the ahah event is being processed the textfield is disabled, which of course means it's value is not submitted. This means validation fails as the textfield is a required field, so the user is returned to the form with an appropriate error. The textfield is always empty when this happens.

If the user waits for the event to finish, the textfield returns to being enabled and submitting works as expected, as does submitting by using the enter key while in the textfield (the event doesn't fire then, so the textfield isn't disabled while it retrieves data).

Is there a way to disable the disabling of the textfield while it's ahah event is being processed, or some other workaround?

Example of the textfield:

$form['id'] = array(
    '#type' => 'textfield',
    '#title' => t('Crop No.'),
    '#default_value' => $crop['id'] ? $crop['id'] : '',
    '#size' => 6,
    '#disabled' => $disabled,
    '#ahah' => array(
        'path' => 'spcs-myspuds/yields/js/crop/description/' . $crop_idx,
        'wrapper' => 'spcs-myspuds-yields-edit-crop-description-row-' . $crop_idx,
        'effect' => 'fade',
        'progress' => array(
            'type' => 'none',
        ),
    ),
);

Thanks in advance for any help.

shareimprove this question
 

I found a workaround.

I had to override Drupal.ahah.prototype.beforeSubmit, the function that disables the input before the submit (well, duh!).

I included the following JavaScript in my module (using drupal_add_js):

$(document).ready(function() {
  if (typeof beforeSubmitOverride == 'undefined' || beforeSubmitOverride == false) {
    Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
      // Disable the element that received the change.
      // IMiJ: Unless it's a text input, otherwise we could submit while element is diabled and loose data.
      if ($(this.element).attr('type') != 'text') {
        $(this.element).addClass('progress-disabled').attr('disabled', true);
      }

      // Insert progressbar or throbber.
      if (this.progress.type == 'bar') {
        var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
        if (this.progress.message) {
          progressBar.setProgress(-1, this.progress.message);
        }
        if (this.progress.url) {
          progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
        }
        this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
        this.progress.object = progressBar;
        $(this.element).after(this.progress.element);
      }
      else if (this.progress.type == 'throbber') {
        this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber">&nbsp;</div></div>');
        if (this.progress.message) {
          $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
        }
        $(this.element).after(this.progress.element);
      }
    };
  };
  beforeSubmitOverride = true;
});

This is a copy of Drupal.ahah.prototype.beforeSubmit as defined in misc/ahah.js with one small change, wrapping the disabling of the input with an if statement to make sure we don't disable text fields.

This is wrapped in a few lines to ensure the re-defining of the prototype happens just once after the DOM is ready.

It might be better to only stop the disabling of the input if a setting is passed such as "disable" => false, but the above worked for the one case in the one page for the one custom module I needed this fix.

shareimprove this answer
 

You can set the #required property TRUE of the textfield to make it a required field.Please set the #disabled property FALSE to check whether it is not occurred due to this.Please remember that #ahah event will call the validate function when it is being processed.

shareimprove this answer
 
   
Thanks for the answer Naveen, but the references to the #required and #disabled parameters are irrelevant in this case (and #disabled is false in the test scenarios anyway otherwise data couldn't be input that triggers the ahah event). The problem is a an issue with the ahah disabling the input while it processes, and the ahah event does not do any validation or trigger any validation hooks. – ianmjones May 1 '12 at 7:10

http://stackoverflow.com/questions/10382736/what-is-the-best-way-to-stop-drupal-textfield-ahah-event...

普通分类: