论坛首页 Web前端技术论坛

CSSHttpRequest 使用记叙

浏览 2178 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-04-01  

首先介绍下这个东西,说白了它跟jsonp很相似,

Like JavaScript includes, this works because CSS is not subject to the same-origin policy that affects XMLHttpRequest. CSSHttpRequest functions similarly to JSONP, and is limited to making GET requests. Unlike JSONP, untrusted third-party JavaScript cannot execute in the context of the calling page.

 

加粗的这句话是说 不像 jsonp在上下文中不信任的第三方js文件不能被执行,这个我没想明白...

 

/* 
CSSHttpRequest
Copyright 2008 nb.io - http://nb.io/
Licensed under Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html
*/

(function(){
    var chr = window.CSSHttpRequest = {};
    
    
    chr.id = 0;
    chr.requests = {};
    chr.MATCH_ORDINAL = /#c(\d+)/;
    chr.MATCH_URL = /url\("?data\:[^,]*,([^")]+)"?\)/;
    
    
    chr.get = function(url, callback) {
        var id = ++chr.id;
        var iframe = document.createElement( "iframe" );
        iframe.style.position = "absolute";
        iframe.style.left = iframe.style.top = "-1000px";
        iframe.style.width = iframe.style.height = 0;
        document.documentElement.appendChild(iframe);
        var r = chr.requests[id] = {
            id: id,
            iframe: iframe,
            document: iframe.contentDocument || iframe.contentWindow.document,
            callback: callback
        };
        
        r.document.open("text/html", false);
        r.document.write("<html><head>");
        r.document.write("<link rel='stylesheet' type='text/css' media='print, csshttprequest' href='" + chr.escapeHTML(url) + "' />");
        r.document.write("</head><body>");
        r.document.write("<script type='text/javascript'>");
        r.document.write("(function(){var w = window; var p = w.parent; p.CSSHttpRequest.sandbox(w); w.onload = function(){p.CSSHttpRequest.callback('" + id + "');};})();");
        r.document.write("</script>");
        r.document.write("</body></html>");
        r.document.close();
    };
    
    
    chr.sandbox = function(w) {
    };
        
    
    chr.callback = function(id) {
        var r = chr.requests[id];
        var data = chr.parse(r);
        r.callback(data);
        window.setTimeout(function() {
            var r = chr.requests[id];
            try { r.iframe.parentElement.removeChild(r.iframe); } catch(e) {};
            delete chr.requests[id];
        }, 0);
    };
    
    chr.parse = function(r) {
        var data = [];
        
        // Safari, IE and same-domain Firefox
        try {
            var rules = r.document.styleSheets[0].cssRules || r.document.styleSheets[0].rules;
            for(var i = 0; i < rules.length; i++) {
                try {
                    var r = rules.item ? rules.item(i) : rules[i];
                    var ord = r.selectorText.match(chr.MATCH_ORDINAL)[1];
                    var val = r.style.backgroundImage.match(chr.MATCH_URL)[1];
                    data[ord] = val;
                } catch(e) {}
            }
        }
        
        // catch same-domain exception
        catch(e) {
            r.document.getElementsByTagName("link")[0].setAttribute("media", "screen");
            var x = r.document.createElement("div");
            x.innerHTML = "foo";
            r.document.body.appendChild(x);
            var ord = 0;
            try {
                while(1) {
                    x.id = "c" + ord;
                    var style = r.document.defaultView.getComputedStyle(x, null);
                    var bg = style["background-image"] || style.backgroundImage || style.getPropertyValue("background-image");
                    var val = bg.match(chr.MATCH_URL)[1];
                    data[ord] = val;
                    ord++;
                }
            } catch(e) {}
        }
        
        return decodeURIComponent(data.join(""));
    };
    
    
    chr.escapeHTML = function(s) {
        return s.replace(/([<>&""''])/g,
            function(m, c) {
                switch(c) {
                    case "<": return "&lt;";
                    case ">": return "&gt;";
                    case "&": return "&amp;";
                    case '"': return "&quot;";
                    case "'": return "&apos;";
                }
                return c;
            });
    };
})();

 

上面是实现的源代码,这个需要后端的支持,比如PHP的后端

<?php
/**
 * CSSHttpRequest PHP Encoder
 *
 * @author Tim Akinbo <obnika@timakinbo.com>, Randy Reddig <ydnar@nb.io>
 * @version 1.2
 * @license http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
 * @copyright Copyright (c) 2008, Tim Akinbo
 */

define('PREFIX', "data:,");
define('LENGTH', 2000 - strlen(PREFIX)); # Internet Explorer 2KB URI limit (http://support.microsoft.com/kb/208427)

function encode($string) {
	$quoted = rawurlencode($string);
	$out = "";
	for ($i = 0, $n = 0; $i < strlen($quoted); $i += LENGTH, $n++) {
		$out .= "#c" . $n . "{background:url(" . PREFIX . substr($quoted, $i, LENGTH) . ");}\n";
	}
	return $out;
}

/* unit test */
if(STDIN) {
    $string = file_get_contents("php://stdin", "r");
    echo encode($string);
}

?>

 官网:

http://nb.io/hacks/csshttprequest

 

感觉还行,其实就是使用 dom元素的 url: data 的机制来实现的, dom这种功能还可以实现一种 本地存储的实现,有兴趣的可以试试

论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics