Drupal7 ajax 应用研究以及invoke方法BUG解决

Events happening in the community are now at Drupal community events on www.drupal.org.
GloolsGuan's picture

Drupal AJAX 系统表单处理流程

  1. 设置

    DRUPAL7 AJAX form 的作用域通常为:

    1. 按钮, 例如各类 button, 和 submit等,可以响应事件。
    2. FORM 各类元素,包含input, textarea, options 等,都可以相应AJAX事件。

    AJAX form 的有效性设置


    $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
    '#ajax' => array(
    'event' => 'click',
    'callback' => 'sample_ajax_render',
    'method' => 'replace'
    )
    );

    AJAX所请求path 需要设置 'delivery callback' => 'ajax_deliver' 如下:

    function SAMPLE_menu(){
    return array(
    'register/%' => array(
    'title' => t('Register'),
    'type' => MENU_CALLBACK,
    'page callback' => 'frontend_register',
    'access arguments' => array('access content'),
    'file' => 'register.page.inc',
    'delivery callback' => 'ajax_deliver'
    )
    );
    }
    注: 该设置标明,该页面的输出需要由ajax_deliver控制,通常输出ajax commands(@see includes/ajax.inc)格式的json字符串,
    并会附加一些其它系统默认操作。

    AJAX元素所设置的callback函数格式:

    function sample_ajax_render(&$form, &$form_state){

    $commands = array();
    
    $commands[] = ajax_command_[REPLACE](....);
    /*
        D7系统内置支持的AJAX命令全部在 includes/ajax.inc 文件中。这里ajax_command_? 设置,是由服务器端设置客户端AJAX响应命令。
        也就是说,这里设置的命令客户端ajax.js 会有响应的操作。比如置换 replace, 附加 append等等。
        注意,这里ajax_command_invoke,默认只支持jQuery内建的方法,如果是你自己开发的方法,通过如下代码加载到jQuery:
        var a=function(){
           this.b = 'hello,world'
        };
        //-- 这里只是申请一个jquery名字空间,并不是实际的设置。
        jQuery.fn.extend(jQuery, a);
        //-- 下面的语句会使jQuery对象化a函数,例如, 在如下语句执行后, 你可以通过 alert(a.b); 得到 “hello,world”输出结果。
        jQuery.a = a;
    
        回到D7 ajax.js, 如上所述,此时如果你在服务器端:
        ajax_command_invoke(NULL, 'a', array(...));
    
        ajax.js 并不能真的调用 a 对象,但是如果这里的 a 是 'addClass'等 jQuery内建对象,则可以正常使用,解决的办法是修改ajax.js源码如下:
    
        //-- Fixed by GloolsGuan@glools.com at 2013-1-6
    
        //-- original drupal7 ajax.js code --
        $element[response.method].apply($element, response.arguments);
        //-----------------------------------
    
        //-- new code for fixing personal jQuery object invoke
        if (undefined==$element[response.method]) {
            $[response.method](response.arguments);
        }else{
            $element[response.method].apply($element, response.arguments);
        }
        //------------------------------------
        将以上原始ajax.js 604行左右, 代码换成新代码即可。
        invoke: function (ajax, response, status);
    */
    
    return array(
        '#type' => 'ajax',
        '#commands' => $ajaxCommands
    );
    

    }

  2. AJAX form的处理流程
    -- PHP 端设置 --

    1. drupal系统根据表单AJAX项设置,会自动加载ajax.inc 文件,包含ajax.js程序。
      -- DRUPAL系统自动处理部分 --
    2. drupal系统会修改表单,在添加有 #ajax项目的FORM 元素上,添加 HTML 节点属性
      class='ajax-processed', 以此标明该节点相应需要AJAX处理。
      -- 客户端相应部分--
    3. 当用户点击或触发AJAX标注的FORM元素时,一个AJAX请求会由ajax.js 建立,并根据设置请求服务器响应。
      -- 服务器端相应部分 --
    4. 服务器接收到AJAX请求依次处理顺序如下:
      1. 处理表单 即 [FORM_ID]_validate, [FORM_ID]_submit等,会先执行。
      2. 调用sample_ajax_render,处理表单输出结果。
        -- D7系统操作部分
      3. 处理sample_ajax_render返回值,并附加系统AJAX相关参数生成JSON字符串,由 ajax_deliver负责最终输出结果。
        换句话说,在sample_ajax_render 中,如果你 直接 print 'hello,world'; AJAX客户端也可以接收,并且服务器端正常运行。
        但是客户端AJAX表示崩溃,因为无法识别数据,当然如果客户端操作你自己写的,另当别论。
    5. 客户端ajax.js根据服务器端返回json格式的drupal7 ajax 命令,依次执行。
    6. 一次AJAX请求流程结束。
  3. 自己调用Drupal.ajax js 对象可以的,注意事项如下,且意义不大:

    1. ajaxInstance = new Drupal.ajax(base, element, element_settings);
    2. base 参数是form表单父级节点。
      element 是当前操作的html元素对象。
      element_settings 是ajax请求相关参数设置,具体参考 ajax.js 这里ajax.js说明很不清楚,得自己研究代码。

Comments

剖析得很好,其实有drupal经验的,看一下ajax

lcnphp's picture

剖析得很好,其实有drupal经验的,看一下ajax comment http://drupal.org/project/ajax_comments模块的代码就完全明白了

剖析得很好,其实有drupal经验的,看一下ajax

lcnphp's picture

剖析得很好,其实有drupal经验的,看一下ajax comment http://drupal.org/project/ajax_comments模块的代码就完全明白了

GloolsGuan's picture

这个模块没有用过,大概扫了一眼,似乎和D7内核AJAX框架有些冲突,不过说实话,drupal7的这一套ajax框架还是很强的。缺点在于DEBUG,不是很方便,同时扩展有些不易。

The creator of GLOOLS.

它就是用ajax_command_*

lcnphp's picture

它就是用ajax_command_*

话说ajax的debug, 你们有什么更好的方法?

rogical's picture

话说ajax的debug, 你们有什么更好的方法? 很多时候dpm是无法输出了,还容易破坏json结构。
用watchdog, 大数组大对象打印的时候又不利于观看。

watchdog('debug', ' '.

lcnphp's picture

watchdog('debug', '

'. print_r($form_state, 1) .'

');

在Glools-Drupal框架中,有一个debug模块,

GloolsGuan's picture

在Glools-Drupal框架中,有一个debug模块,专门负责服务器端debug, 通过命令窗口,及时获取调试信息。 在ajax 的客户端JS部分有一个类似的TEST.js 程序也是用来做客户端调试的,可以输出一个对象。

基于服务器端的DEBUG目录结构要求
www.domain.com/
webroot/drupal code
debug/???.txt

使用命令 tail -f debug/???.txt -n 100 可以及时获取测试信息。

The creator of GLOOLS.

< pre> 居然被过滤了

lcnphp's picture

< pre> 居然被过滤了

用watchdog加上pre 也打印出 树状点击折叠的

rogical's picture

用watchdog加上pre 也打印出 树状点击折叠的 dpm效果吧

rogical's picture

用watchdog加上pre 也打印不出 树状点击折叠的 dpm效果吧

达不到dom那么好看,起码舒服很多了

lcnphp's picture

达不到dom那么好看,起码舒服很多了

Form 元素使用D7 ajax

hooface's picture

Form 元素使用D7 ajax 很方便,如果不了解JS,可以不用写行 JS 代码,但扩展比较麻烦一些,虽然提供了一些 hook,要熟悉一下也是需要时间的。
对于非表单元素,我喜欢直接使用 JQuery.ajax,流程也好控制。
有兴趣的可以看看 http://dev.twippo.com 这个网站,大量使用了 ajax ,但需要注册一下用户才可体验某些功能。

D7, 的AJAX

GloolsGuan's picture

D7, 的AJAX 非表单部分操作,和客户自定义JS,引用却有问题,这就是为什么发布这个帖子,并提供了修复方法的原因。不过修复后,要求自己开发的js组件,必须注册为jQuery的对象。否则还是无效。

The creator of GLOOLS.

我在项目中没有遇到什么问题

hooface's picture

我在项目中没有遇到什么问题。
你指的“引用却有问题”能具体点吗?
另外你说的”自己开发的js组件,必须注册为jQuery的对象“,这可能是名字空间引起的,为了防止客户的 js 与核心或其他 js库 冲突,Drupal 7 将 jQuery 作为一个名字空间,具体可以看看这篇文档:http://drupal.org/node/756722

DrupalHK

Group categories

HKDUG Vocabulary

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: