mass Framework ajax模块

由于ajax模块要涉及到后台的配合才能看到后台,因此我先给出后台代码,如果会rails的人,可以复制下来搭建相应的运行环境。

控制器部分




class HomeController < ApplicationController

   skip_before_filter :verify_authenticity_token  



  def index

    #如果XMLHttpRequest请求

    if request.xhr?

      respond_to do |format|

        format.json do 

          p "format.json"

          render :json => {

            "aaa"=>"ruby",

            "bbb"=>"louvre",

            "ccc"=>{

              "ddd"=>Time.now,

              "eee"=>"司徒正美"

            }

          }

        end

        format.html do 

          render 'home/html_test.erb'

        end

        format.text do

          p "format.text"

          render :text=> "输出纯文本消息"

        end

        format.js do

          p "format.js"

          render :js => "alert('Hello Rails');"

        end        

        format.xml do

          p "format.xml"

          #http://ap.rubyonrails.org/classes/Builder/XmlMarkup.html

          render :template => 'home/test.rxml', :layout => false

        end

      end

    end

  end

  

  def upload

    render :text => "OK"

  end



end

视图部分:

html_test.erb


<table class="blue_table">

  <colgroup><col class="grey" width="30%">

  <col class="yellow">

  </colgroup><thead>

    <tr>

      <th colspan="2">javascript相关的小研究心得</th>

    </tr>

  </thead>

  <tbody>

     <tr>

      <td><a href="2009/11/06/1597523.html">获取函数名</a></td>

      <td><a href="2011/01/05/1926226.html">iframe高度自适应</a></td>

   </tr>

      <tr>

      <td><a href="2010/01/20/1652646.html">类型判定</a></td>

      <td><a href="2010/05/25/1742173.html">jsonp跨域</a></td>

   </tr>

   <tr>

      <td><a href="2010/05/18/1738034.html">修复IE6 base bug</a></td>

      <td><a href="2010/04/06/1705817.html">getBasePath函数</a></td>

   </tr>

    <tr>

      <td><a href="2010/04/15/1712780.html">domReady</a></td>

      <td><a href="2009/10/14/1583362.html">判定浏览器</a></td>

    </tr>

    <tr>

      <td><a href="2009/09/24/1572977.html">获取随机颜色</a></td>

      <td><a href="2009/10/14/1583523.html">contains函数</a></td>

    </tr>

    <tr>

      <td><a href="2009/10/30/1593094.html">惰性函数</a></td>

      <td><a href="2009/11/09/1598761.html">currying函数</a></td>

    </tr>

    <tr>

      <td><a href="2009/11/08/1598383.html">字符串的乘法</a></td>

      <td><a href="2009/10/31/1593484.html">javascript 动态解析脚本</a></td>

    </tr>

    <tr>

      <td><a href="2009/11/13/1602122.html">动态this与动态绑定</a></td>

      <td><a href="2009/11/10/1599978.html">forEach函数</a></td>

    </tr>

    <tr>

      <td><a href="2009/07/17/1525637.html">移除DOM节点</a></td>

      <td><a href="2009/07/24/1529640.html">getElementsByClassName</a></td>

    </tr>

    <tr>

      <td><a href="2009/07/24/1530020.html">跨浏览器的事件写法</a></td>

      <td><a href="2009/07/24/1530074.html">javascript的闭包</a></td>

    </tr>

    <tr>

      <td><a href="2009/08/01/1536710.html">iframe元素用法总结</a></td>

      <td><a href="2009/08/08/1541578.html">javascript AOP实现</a></td>

    </tr>

    <tr>

      <td><a href="2009/08/19/1550088.html">JS类写法的性能研究</a></td>

      <td><a href="2009/08/20/1550526.html">javascript 键盘事件总结</a></td>

    </tr>

    <tr>

      <td><a href="2009/08/21/1551270.html">javascript变量的作用域</a></td>

      <td><a href="2009/10/07/1578629.html">动态加载图片与脚本</a></td>

    </tr>

    <tr>

      <td><a href="2009/08/09/1542174.html">javascript事件代理</a></td>

      <td><a href="2009/08/26/1554204.html">javascript的事件加载</a></td>

    </tr>

  <tr>

      <td><a href="2010/01/06/1640148.html">高效地获取XMLhttp对象</a></td>

      <td><a href="2009/08/24/1552862.html">javascript的鼠标事件</a></td>

    </tr>

    <tr>

      <td><a href="2009/07/14/1523104.html">动态添加样式表规则</a> <a href="2009/08/30/1556869.html">2</a></td>

      <td><a href="2010/02/11/1667364.html">自动执行函数</a></td>

    </tr>

    <tr>

      <td><a href="2009/09/05/1559883.html">精确获取样式属性</a> <a href="2009/09/08/1562212.html">2</a></td>

      <td><a href="2009/09/08/1562444.html">精确获取页面元素的位置</a></td>

    </tr>

    <tr>

      <td><a href="2010/02/11/1667364.html">自动执行函数</a></td>

      <td><a href="2009/07/24/1530020.html">事件兼容</a></td>

    </tr>

   <tr>

      <td><a href="2009/09/16/1566699.html">缓动效果</a> <a href="2009/09/17/1567607.html">2</a></td>

      <td><a href="2009/10/01/1577219.html">无缝滚动</a> <a href="2009/10/03/1577735.html">2</a></td>

    </tr>

    <tr>

      <td><a href="2009/09/30/1576699.html">javascript图片轮换</a> <a href="2009/10/06/1578289.html">2</a></td>

      <td>

        <a href="2009/10/09/1578966.html">javascript线性渐变</a> 

        <a href="2009/10/10/1580061.html">2</a> 

        <a href="2009/10/14/1582876.html">3</a> 

    </td>

    </tr>

  </tbody>

</table>

test.rxml




xml = Builder::XmlMarkup.new

xml.instruct!                   # 
 
   

xml.html {                      # 

  xml.head {                    #   

    xml.title("History")        #     History

  }                            #   

  xml.body {                    #   

    xml.comment! "HI"           #     
 
   

    xml.h1("Header")            #     

Header

xml.p("paragraph") #

paragraph

} # }

路由配置


  map.resources  :homes, :member => {:upload => :post }

  map.home '' ,:controller => 'home',:action => 'index'

ajax模块源码:


//数据请求模块

(function(global,DOC){

    var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')];

    dom.define("ajax","node,emitter", function(){

        dom.log("已加载ajax模块");

        var r20 = /%20/g,

        rCRLF = /\r?\n/g,

        encode = global.encodeURIComponent,

        rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL

        rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,

        rnoContent = /^(?:GET|HEAD)$/,

        rquery = /\?/,

        rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,

        // Document location

        ajaxLocation

        // #8138, IE may throw an exception when accessing

        // a field from window.location if document.domain has been set

        try {

            ajaxLocation = global.location.href;

        } catch( e ) {

            // Use the href attribute of an A element

            // since IE will modify it given document.location

            ajaxLocation = DOC.createElement( "a" );

            ajaxLocation.href = "";

            ajaxLocation = ajaxLocation.href;

        }



        // Segment location into parts

        var ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [],

        transports = { },//传送器

        converters ={//转换器

            text: function(dummyXHR,text,xml){

                return text != undefined ? text : ("xml" in xml ?  xml.xml: new XMLSerializer().serializeToString(xml));

            },

            xml : function(dummyXHR,text,xml){

                return xml != undefined ? xml : dom.parseXML(text);

            },

            html : function(dummyXHR,text,xml){

                return  dom.parseHTML(text);

            },

            json : function(dummyXHR,text,xml){

                return  dom.parseJSON(text);

            },

            script: function(dummyXHR,text,xml){

                dom.globalEval(text);

            }

        },

        accepts  = {

            xml: "application/xml, text/xml",

            html: "text/html",

            text: "text/plain",

            json: "application/json, text/javascript",

            script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript",

            "*": "*/*"

        },

        defaultOptions = {

            type:"GET",

            contentType: "application/x-www-form-urlencoded; charset=UTF-8",

            async:true,

            dataType:"text",

            jsonp: "callback"

        };



        function normalizeOptions(o) {

            // deep mix

            o = dom.Object.merge.call( {},defaultOptions, o);

            //判定是否跨域

            if (o.crossDomain == null) {

                var parts = rurl.exec(o.url.toLowerCase());

                o.crossDomain = !!( parts &&

                    ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||

                        ( parts[ 3 ] || ( parts[ 1 ] === "http:" ?  80 : 443 ) )

                        !=

                        ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ?  80 : 443 ) ) )

                    );

            }

            //转换data为一个字符串

            if ( o.data && o.data !== "string") {

                o.data = dom.param( o.data );

            }

            //type必须为大写

            o.type = o.type.toUpperCase();

            o.hasContent = !rnoContent.test(o.type);



            if (!o.hasContent) {//如果为GET请求,则参数依附于url上

                if (o.data) {

                    o.url += (rquery.test(o.url) ? "&" : "?" ) + o.data;

                }

                if (o.cache === false) {

                    o.url += (rquery.test(o.url) ? "&" : "?" ) + "_time=" + Date.now();

                }

            }

            return o;

        }



        "get post".replace(dom.rword,function(method){

            dom[ method ] = function( url, data, callback, type ) {

                // shift arguments if data argument was omitted

                if ( dom.isFunction( data ) ) {

                    type = type || callback;

                    callback = data;

                    data = undefined;

                }

                return dom.ajax({

                    type: method,

                    url: url,

                    data: data,

                    success: callback,

                    dataType: type

                });

            };



        });



        dom.mix(dom,{

            getScript: function( url, callback ) {

                return dom.get( url, null, callback, "script" );

            },



            getJSON: function( url, data, callback ) {

                return dom.get( url, data, callback, "json" );

            },

            upload: function(url, form, data, callback, dataType) {

                if (dom.isFunction(data)) {

                    dataType = callback;

                    callback = data;

                    data = undefined;

                }

                return dom.ajax({

                    url:url,

                    type:'post',

                    dataType:dataType,

                    form:form,

                    data:data,

                    success:callback

                });

            },

            serialize : function(form) {

                return dom.param(dom.serializeArray(form));

            },

            serializeArray : function(form){

                // 不直接转换form.elements,防止以下情况:   <form > <input name="elements"/><input name="test"/></form>

                var elements = dom.slice(form||[]), ret = []

                elements.forEach(function(elem){

                    if( elem.name && !elem.disabled && ( "checked" in elem ? elem.checked : 1 )){

                        var val = dom( elem ).val();

                        if(Array.isArray(val)){

                            val.forEach(function(value){

                                ret.push({

                                    name: elem.name,

                                    value: value.replace( rCRLF, "\r\n" )

                                });

                            });

                        }else if(typeof val == "string"){

                            ret.push({

                                name: elem.name,

                                value: val.replace( rCRLF, "\r\n" )

                            });

                        }

                    }

                });

                return ret;

            },

            param : function( object ) {//objectToQuery

                var ret = [];

                function add( key, value ){

                    ret[ ret.length ] = encode(key) + '=' + encode(value);

                }

                if ( Array.isArray(object) ) {

                    for ( var i = 0, length = object.length; i < length; i++ ) {

                        add( object[i].name, object[i].value );

                    }

                } else {

                    function buildParams(obj, prefix) {

                        if ( Array.isArray(obj) ) {

                            for ( var i = 0, length = obj.length; i < length; i++ ) {

                                buildParams( obj[i], prefix );

                            }

                        } else if( dom.isPlainObject(obj) ) {

                            for ( var j in obj ) {

                                var postfix = ((j.indexOf("[]") > 0) ? "[]" : ""); // move the brackets to the end (if applicable)

                                buildParams(obj[j], (prefix ? (prefix+"["+j.replace("[]", "")+"]"+postfix) : j) );

                            }

                        } else {

                            add( prefix, dom.isFunction(obj) ? obj() : obj );

                        }

                    }

                    buildParams(obj);

                }

                return ret.join("&").replace(r20, "+");

            }

        });



        var ajax = dom.ajax = function(object) {

            if (!object.url) {

                return undefined;

            }

            var options = normalizeOptions(object),//规整化参数对象

            //创建一个伪XMLHttpRequest,能处理complete,success,error等多投事件

            dummyXHR = new dom.jXHR(options),

            dataType = options.dataType;



            if(options.form && options.form.nodeType ==1){

                dataType = "iframe";

            }else if(dataType == "jsonp"){

                if(options.crossDomain){

                    ajax.fire("start", dummyXHR, options.url,options.jsonp);//用于jsonp请求

                    dataType = "script"

                }else{

                    dataType = dummyXHR.options.dataType = "json";

                }

            }

            var transportContructor = transports[dataType] || transports._default,

            transport = new transportContructor();

            transport.dummyXHR = dummyXHR;

            dummyXHR.transport = transport;

            if (options.contentType) {

                dummyXHR.setRequestHeader("Content-Type", options.contentType);

            }



            //添加dataType所需要的Accept首部

            dummyXHR.setRequestHeader( "Accept", accepts[dataType] ? accepts[ dataType ] +  ", */*; q=0.01"  : accepts[ "*" ] );

            for (var i in options.headers) {

                dummyXHR.setRequestHeader(i, options.headers[ i ]);

            }



            "Complete Success Error".replace(dom.rword, function(name){

                var method = name.toLowerCase();

                dummyXHR[method] = dummyXHR["on"+name];

                if(typeof options[method] === "function"){

                    dummyXHR[method](options[method]);

                    delete dummyXHR.options[method];

                    delete options[method];

                }

            });

            dummyXHR.readyState = 1;

            // Timeout

            if (options.async && options.timeout > 0) {

                dummyXHR.timeoutID = setTimeout(function() {

                    dummyXHR.abort("timeout");

                }, options.timeout);

            }



            try {

                dummyXHR.state = 1;//已发送

                transport.send();

            } catch (e) {

                if (dummyXHR.status < 2) {

                    dummyXHR.callback(-1, e);

                } else {

                    dom.log(e);

                }

            }



            return dummyXHR;

        }



        dom.mix(ajax, dom.emitter);

        ajax.isLocal = rlocalProtocol.test(ajaxLocParts[1]);

        /**

         * jXHR类,用于模拟原生XMLHttpRequest的所有行为

         */

        dom.jXHR = dom.factory({

            include:dom.emitter,

            init:function(option){

                dom.mix(this, {

                    responseData:null,

                    timeoutID:null,

                    responseText:null,

                    responseXML:null,

                    responseHeadersString:"",

                    responseHeaders:null,

                    requestHeaders:{},

                    readyState:0,

                    //internal state

                    state:0,

                    statusText:null,

                    status:0,

                    transport:null

                });



                this.defineEvents("complete success error");

                this.setOptions(option);

            },



            fire: function(type){

                var target = this, table = dom.data( target,"@events") ,args = dom.slice(arguments,1);

                if(!table) return;

                var queue = table[type];

                if (  queue ) {

                    for ( var i = 0, bag; bag = queue[i++]; ) {

                        bag.callback.apply( target, args );

                    }

                }

            },



            setRequestHeader: function(name, value) {

                this.requestHeaders[ name ] = value;

                return this;

            },



            getAllResponseHeaders: function() {

                return this.state === 2 ? this.responseHeadersString : null;

            },

            getResponseHeader: function(key,/*internal*/ match) {

                if (this.state === 2) {

                    if (!this.responseHeaders) {

                        this.responseHeaders = {};

                        while (( match = rheaders.exec(this.responseHeadersString) )) {

                            this.responseHeaders[ match[1] ] = match[ 2 ];

                        }

                    }

                    match = this.responseHeaders[ key];

                }

                return match === undefined ? null : match;

            },

            // 重写 content-type 首部

            overrideMimeType: function(type) {

                if (!this.state) {

                    this.mimeType = type;

                }

                return this;

            },



            // 中止请求

            abort: function(statusText) {

                statusText = statusText || "abort";

                if (this.transport) {

                    this.transport._callback(0, 1);

                }

                this.callback(0, statusText);

                return this;

            },

            /**

             * 用于触发success,error,complete等回调

             * http://www.cnblogs.com/rubylouvre/archive/2011/05/18/2049989.html

             * @param {Number} status 状态码

             * @param {String} statusText 对应的扼要描述

             */

            callback:function(status, statusText) {

                // 只能执行一次,防止重复执行

                // 例如完成后,调用 abort

                // 到这要么成功,调用success, 要么失败,调用 error, 最终都会调用 complete

                if (this.state == 2) {//2:已执行回调

                    return;

                }

                this.state = 2;

                this.readyState = 4;

                var isSuccess;

                if (status >= 200 && status < 300 || status == 304) {

                    if (status == 304) {

                        statusText = "notmodified";

                        isSuccess = true;

                    } else {

                        var text = this.responseText, xml = this.responseXML,dataType = this.options.dataType;

                        try{

                            dom.log(text)

                            this.responseData = converters[dataType](this, text, xml);

                            statusText = "success";

                            isSuccess = true;

                            dom.log("dummyXHR.callback success");

                        } catch(e) {

                            dom.log("dummyXHR.callback parsererror")

                            statusText = "parsererror : " + e;

                        }

                    }



                }

                else {

                    if (status < 0) {

                        status = 0;

                    }

                }



                this.status = status;

                this.statusText = statusText;

                if (this.timeoutID) {

                    clearTimeout(this.timeoutID);

                }

                if (isSuccess) {

                    this.fire("success",this.responseData,statusText);

                } else {

                    this.fire("error",this.responseData,statusText);

                }

                this.fire("complete",this.responseData,statusText);

                this.transport = undefined;

            }

        });



        //http://www.cnblogs.com/rubylouvre/archive/2010/04/20/1716486.html

        //【XMLHttpRequest】传送器,专门用于上传

        var s = ["XMLHttpRequest",

        "ActiveXObject('Msxml2.XMLHTTP.6.0')",

        "ActiveXObject('Msxml2.XMLHTTP.3.0')",

        "ActiveXObject('Msxml2.XMLHTTP')",

        "ActiveXObject('Microsoft.XMLHTTP')"];

        if( !-[1,] && global.ScriptEngineMinorVersion() === 7 && location.protocol === "file:"){

            s.shift();

        }

        for(var i = 0 ,axo;axo = s[i++];){

            try{

                if(eval("new "+ axo)){

                    dom.xhr = new Function( "return new "+axo);

                    break;

                }

            }catch(e){}

        }

        if (dom.xhr) {

            var nativeXHR = new dom.xhr(), allowCrossDomain = false;

            if ("withCredentials" in nativeXHR) {

                allowCrossDomain = true;

            }

            //添加通用XMLHttpRequest传送器

            transports._default =  dom.factory({

                //发送请求

                send:function() {

                    var self = this,

                    dummyXHR = self.dummyXHR,

                    options = dummyXHR.options;

                    dom.log("XhrTransport.sending.....");

                    if (options.crossDomain && !allowCrossDomain) {

                        dom.error("do not allow crossdomain xhr !");

                        return;

                    }



                    var nativeXHR = new dom.xhr(), i;

                    self.xhr = nativeXHR;

                    if (options.username) {

                        nativeXHR.open(options.type, options.url, options.async, options.username, options.password)

                    } else {

                        nativeXHR.open(options.type, options.url, options.async);

                    }

                    // Override mime type if supported

                    if (dummyXHR.mimeType && nativeXHR.overrideMimeType) {

                        nativeXHR.overrideMimeType(dummyXHR.mimeType);

                    }

                    // 用于进入request.xhr?分支

                    if (!options.crossDomain && !dummyXHR.requestHeaders["X-Requested-With"]) {

                        dummyXHR.requestHeaders[ "X-Requested-With" ] = "XMLHttpRequest";

                    }

                    try {

                        for (i in dummyXHR.requestHeaders) {

                            nativeXHR.setRequestHeader(i, dummyXHR.requestHeaders[ i ]);

                        }

                    } catch(e) {

                        dom.log(" nativeXHR setRequestHeader occur error ");

                    }



                    nativeXHR.send(options.hasContent && options.data || null);

                    //在同步模式中,IE6,7可能会直接从缓存中读取数据而不会发出请求,因此我们需要手动发出请求

                    if (!options.async || nativeXHR.readyState == 4) {

                        self._callback();

                    } else {

                        nativeXHR.onreadystatechange = function() {

                            self._callback();

                        }

                    }

                },



                //用于获取原始的responseXMLresponseText 修正status statusText

                //第二个参数为1时中止清求

                _callback:function(event, isAbort) {

                    // Firefox throws exceptions when accessing properties

                    // of an xhr when a network error occured

                    // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)

                    try {

                        var self = this,nativeXHR = self.xhr, dummyXHR = self.dummyXHR;

                        if (isAbort || nativeXHR.readyState == 4) {

                            nativeXHR.onreadystatechange = dom.noop;

                            if (isAbort) {

                                // 完成以后 abort 不要调用

                                if (nativeXHR.readyState !== 4) {

                                    //IE的XMLHttpRequest.abort实现于 MSXML 3.0+

                                    //http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx

                                    try{

                                        nativeXHR.abort &&  nativeXHR.abort();

                                    }catch(e){};

                                }

                            } else {

                                var status = nativeXHR.status;

                                dummyXHR.responseHeadersString = nativeXHR.getAllResponseHeaders();

                                var xml = nativeXHR.responseXML;

                                // Construct response list

                                if (xml && xml.documentElement /* #4958 */) {

                                    dummyXHR.responseXML = xml;

                                }

                                dummyXHR.responseText = nativeXHR.responseText;

                                //火狐在跨城请求时访问statusText值会抛出异常

                                try {

                                    var statusText = nativeXHR.statusText;

                                } catch(e) {

                                    statusText = "";

                                }

                                //用于处理特殊情况,如果是一个本地请求,只要我们能获取数据就假当它是成功的

                                if (!status && ajax.isLocal && !dummyXHR.options.crossDomain) {

                                    status = dummyXHR.responseText ? 200 : 404;

                                //IE有时会把204当作为1223

                                //returning a 204 from a PUT request - IE seems to be handling the 204 from a DELETE request okay.

                                } else if (status === 1223) {

                                    status = 204;

                                }

                                dummyXHR.callback(status, statusText);

                            }

                        }

                    } catch (firefoxAccessException) {

                        dom.log(firefoxAccessException)

                        nativeXHR.onreadystatechange = dom.noop;

                        if (!isAbort) {

                            dummyXHR.callback(-1, firefoxAccessException);

                        }

                    }

                }

            });



        }

        //【script节点】传送器,只用于跨域的情况

        transports.script = dom.factory({

            send:function() {

                var self = this,

                dummyXHR = self.dummyXHR,

                options = dummyXHR.options,

                head = dom.HEAD,

                script = self.script = DOC.createElement("script");

                script.async = "async";

                dom.log("ScriptTransport.sending.....");

                if (options.charset) {

                    script.charset = options.charset

                }

                //当script的资源非JS文件时,发生的错误不可捕获

                script.onerror = script.onload = script.onreadystatechange = function(e) {

                    e = e || global.event;

                    self._callback((e.type || "error").toLowerCase());

                };

                script.src = options.url

                head.insertBefore(script, head.firstChild);

            },



            _callback:function(event, isAbort) {

                var node = this.script,

                dummyXHR = this.dummyXHR;

                if (isAbort || dom.rreadystate.test(node.readyState)  || event == "error"  ) {

                    node.onerror = node.onload = node.onreadystatechange = null;

                    var parent = node.parentNode;

                    if(parent && parent.nodeType === 1){

                        parent.removeChild(node);

                        this.script = undefined;

                    }

                    //如果没有中止请求并没有报错

                    if (!isAbort && event != "error") {

                        dummyXHR.callback(200, "success");

                    }

                    // 非 ie<9 可以判断出来

                    else if (event == "error") {

                        dummyXHR.callback(500, "scripterror");

                    }

                }

            }

        });



        //http://www.decimage.com/web/javascript-cross-domain-solution-with-jsonp.html

        //JSONP请求,借用【script节点】传送器

        converters["script json"] = function(dummyXHR){

            return dom["jsonp"+ dummyXHR.uniqueID ]();

        }

        ajax.bind("start", function(e, dummyXHR, url, jsonp) {

            dom.log("jsonp start...");

            var jsonpCallback = "jsonp"+dummyXHR.uniqueID;

            dummyXHR.options.url = url  + (rquery.test(url) ? "&" : "?" ) + jsonp + "=" + DOC.URL.replace(/(#.+|\W)/g,'')+"."+jsonpCallback;

            dummyXHR.options.dataType = "script json";

            //将后台返回的json保存在惰性函数中

            global.dom[jsonpCallback]= function(json) {

                global.dom[jsonpCallback] = function(){

                    return json;

                };

            };

        });



        function createIframe(dummyXHR, transport) {

            var id = "iframe-upload-"+dummyXHR.uniqueID;

            var iframe = dom.parseHTML("<iframe " +

                " id='" + id + "'" +

                " name='" + id + "'" +

                " style='display:none'/>").firstChild;

            iframe.transport = transport;

            return   (DOC.body || DOC.documentElement).insertBefore(iframe,null);

        }



        function addDataToForm(data, form) {

            var input = DOC.createElement("input"), ret = [];

            input.type = 'hidden';

            dom.serializeArray(data).forEach(function(obj){

                var elem =  input.cloneNode(true);

                elem.name = obj.name;

                elem.value = obj.value;

                form.appendChild(elem);

                ret.push(elem);

            });

            return ret;

        }

        //【iframe】传送器,专门用于上传

        //http://www.profilepicture.co.uk/tutorials/ajax-file-upload-xmlhttprequest-level-2/ 上传

        transports.iframe = dom.factory({

            send:function() {

                var self = this,

                dummyXHR = self.dummyXHR,

                options = dummyXHR.options,

                form = options.form

                //form.enctype的值

                //1:application/x-www-form-urlencoded	在发送前编码所有字符(默认)

                //2:multipart/form-data	不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。

                //3:text/plain	空格转换为 "+" 加号,但不对特殊字符编码。

                this.backups = {

                    target:form.target || "",

                    action:form.action || "",

                    enctype:form.enctype,

                    method:form.method

                };



                var iframe = createIframe(dummyXHR, this);

                //必须指定method与enctype,要不在FF报错

                //“表单包含了一个文件输入元素,但是其中缺少 method=POST 以及 enctype=multipart/form-data,所以文件将不会被发送。”

                // 设置target到隐藏iframe,避免整页刷新

                form.target =  "iframe-upload-"+dummyXHR.uniqueID;

                form.action =  options.url;

                form.method =  "POST";

                form.enctype = "multipart/form-data";

                this.fields = options.data ? addDataToForm(options.data, form) : [];

                this.form = form;//一个表单元素

                dom.log("iframe transport...");

                dom(iframe).bind("load",this._callback).bind("error",this._callback);

                form.submit();

            },



            _callback:function(event  ) {

                var iframe = this,

                transport =  iframe.transport;

                // 防止重复调用 , 成功后 abort

                if (!transport) {

                    return;

                }

                dom.log("transports.iframe _callback")

                var form = transport.form,

                eventType = event.type,

                dummyXHR = transport.dummyXHR;

                iframe.transport = undefined;

                if (eventType == "load") {

                    var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;

                    var iframeDoc = iframe.contentWindow.document;

                    if (doc.XMLDocument) {

                        dummyXHR.responseXML = doc.XMLDocument;

                    } else if (doc.body){

                        // response is html document or plain text

                        dummyXHR.responseText = doc.body.innerHTML;

                        dummyXHR.responseXML = iframeDoc;

                        //当,MIME为"text/plain",浏览器会把文本放到一个PRE标签中

                        if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {

                            dummyXHR.responseText  = doc.body.firstChild.firstChild.nodeValue;

                        }

                    }else {

                        // response is a xml document

                        dummyXHR.responseXML = doc;

                    }

                    dummyXHR.callback(200, "success");

                } else if (eventType == 'error') {

                    dummyXHR.callback(500, "error");

                }

                for(var i in transport.backups){

                    form[i] = transport.backups[i];

                }

                //还原form的属性

                transport.fields.forEach(function(elem){

                    elem.parentNode.removeChild(elem);

                });

                dom(iframe).unbind("load",transport._callback).unbind("error",transport._callback);

                iframe.clearAttributes &&  iframe.clearAttributes();

                setTimeout(function() {

                    // Fix busy state in FF3

                    iframe.parentNode.removeChild(iframe);

                    dom.log("iframe.parentNode.removeChild(iframe)")

                }, 0);



            }

        });



    });



})(this,this.document);

//2011.8.31

//将会传送器的abort方法上传到dom.jXHR.abort去处理

//修复serializeArray的bug

//对XMLHttpRequest.abort进行try...catch

JSONP请求示例


        dom.ajax({

          url:"http://del.icio.us/feeds/json/fans/stomita",

          type:"get",

          success:function(responseData){

            dom.log(responseData+"  success");

          },

          dataType:"jsonp"

        });



api基本与jQuery兼容,如get,post,getScript,getJSON,ajax等等,还多出一个upload用于iframe上传。

一个上传示例:




      dom.require("ready,ajax,event",function(){

        dom("#i33").click(function(e){

          dom.log("click")

          dom.upload("/home/upload",dom("#aaa")[0],function(text){

            alert(text)

          });

        })

      });

对应的页面:


    <form id="aaa" >

      <input type="file" id="file" name="file" style="width:450"/>

      <input type="submit" value="上传文件" id="i33"/>

      <span id="msg"></span>

      <br/>

      <font color="red">支持JPG,JPEG,GIF,BMP,SWF,RMVB,RM,AVI文件的上传</font>

    </form>

你可能感兴趣的:(framework)