lundi 3 mai 2010

[Javascript] Encapsuler du javascript, du css et des images dans une seule et même image

Bonjour,
Il y'a quelques mois j'ai eu besoin d'encapsuler tout mes scripts, css et images dans une seul image, puis appeler cette image avec AJAX, et extraire le tout pour l'insérer dans le document. Je ne sais pas si ça va servir mais c'est intéressant de voir que ça marche ;-)


Donc, pour le tester, créez un dossier sur un serveur, mettez tout vos scripts, css et images (vous pouvez les mettre à la racine, dans des dossiers,...etc comme vous voulez), éventuellement numérotez vos scripts 1.js, 2.js, ... etc au cas ou l'un doit être inclus avant l'autre.
Mettez dans la racine du dossier une image nommée js.png, c'est elle qui va intégrer les scripts et les css.Mettez dans la racine du dossier ce script PHP:

<?
// embed images as data:image/gif;base64,...
function read_from_file ($file) {
$handle = @fopen($file, "r");
$data = '';
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$data .= $buffer;
}
fclose($handle);
}
return rtrim($data);
}
function write_to_file ($file, $data) {
$fp = fopen($file, "w");
fwrite($fp, $data);
fclose($fp);
}
function lReplace($m) {
echo " : image ".$GLOBALS['dn'].'/'.$m[1].'.'.$m[3]." base64 encoded in".$GLOBALS['fn']."<br>";
return "data:image/gif;base64,".base64_encode(read_from_file($GLOBALS['dn'].'/'.$m[1].'.'.$m[3]));
}
function lParse($dirname,$file) {
$GLOBALS['dn'] = $dirname;
$GLOBALS['fn'] = $dirname."/".$file;
$path = $dirname."/".$file;
$data = read_from_file($path);
write_to_file($path,preg_replace_callback('/([^\'\(\."\s]*)(\.)(gif|jpg|bmp|png)/i',lReplace,$data));
}
function read_dir1($dirname,$i) {
$j=$i+1;
$ind="";
while($i) {$ind .= '__';$i--;}
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)) {
echo $ind.$dirname."/".$file."<br>";
if(preg_match('/.(\.)(css|js)/',$file)) {lParse($dirname,$file);}
}
else
read_dir1($dirname.'/'.$file,$j);
}
}
closedir($dir_handle);
return true;
}
read_dir1('.',0);


// embed css and js in an image
function store($d,$f) {
if(preg_match('/.(\.)(js)$/',$f)) $GLOBALS['data_js'] .= read_from_file($d."/".$f);
if(preg_match('/.(\.)(js)$/',$f)) $GLOBALS['data_js'] .= "\n\n";
if(preg_match('/.(\.)(css)$/',$f)) $GLOBALS['data_css'] .= read_from_file($d."/".$f);
if(preg_match('/.(\.)(css)$/',$f)) $GLOBALS['data_css'] .= "\n\n";
}
$ord = 1;

if($ord) {
function reador_dir($dirname,$i,$max) {
$j=$i+1;
$ind="";
while($i) {$ind .= '__';$i--;}
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)) {
if(preg_match('/(\d){1,2}(\.)(js)$/',$file,$m) && $m[1]>$max) {$max=$m[1];}
}
else
$max = reador_dir($dirname.'/'.$file,$j,$max);
}
}
closedir($dir_handle);
return $max;
}

function storord($dirname,$i) {
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)) {
if(preg_match("/$i(\.)(js)$/",$file)) {store($dirname,$file);echo "store($dirname/$file)<br>";}
}
else
storord($dirname.'/'.$file,$i);
}
}
closedir($dir_handle);
return false;
}

echo "max is ".reador_dir('.',0,1)."<br>";
$i=1;
while($i<reador_dir('.',0,1)+1) {storord('.',$i); $i++;}
}
function read_dir2($dirname,$i,$ord) {
$j=$i+1;
$ind="";
while($i) {$ind .= '__';$i--;}
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)) {
if(preg_match('/.(\.)(css|js)$/',$file) && !$ord) {store($dirname,$file);echo "store($dirname/$file)<br>";}
elseif(preg_match('/.(\.)(css|js)$/',$file) && !preg_match('/(\d){1,2}(\.)(css|js)$/',$file)) {store($dirname,$file);echo "store($dirname/$file)<br>";}
}
else
read_dir2($dirname.'/'.$file,$j,$ord);
}
}
closedir($dir_handle);
return true;
}
read_dir2('.',0,$ord);
write_to_file ("js.png", read_from_file("js.png")."\n[JS]".$GLOBALS['data_js']."\n[CSS]".$GLOBALS['data_css']);
?>
Lancez ce script PHP, vous remarquerez qu'a la fin la taille de l'image aura considérablement augmenté, maintenant, dans la page qui doit inclure ce que vous avez encapsulé dans l'image, mettre le code javascript suivant:

<script>

function get_js (url) {
var request = false;
if(window.XMLHttpRequest) {
request = new XMLHttpRequest();
if(request.overrideMimeType) {
request.overrideMimeType('text/xml');
}
} else if(window.ActiveXObject) {
var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for(var i=0; i<versions.length; i++) {
try {
request = new ActiveXObject(versions[i]);
} catch(e) {}
}
}
xmlHttpReq = request;
xmlHttpReq.open("GET",url, false);
//xmlHttpReq.onload = load_image(xmlHttpReq.responseText);
xmlHttpReq.send(null);
return xmlHttpReq.responseText;
}

function ress(resp,type) {
var b1 = resp.indexOf('[JS]') + 4;
var b2 = resp.indexOf('[CSS]') + 5;
var delb = b2-b1-5;
if(type=="js") return resp.substr(b1,delb);
if(type=="css") return resp.substring(b2);
}

var resp = get_js('js.png','js');
var html_doc = document.getElementsByTagName('head').item(0);
var js = document.createElement('script'); js.textContent = ress(resp,'js'); html_doc.appendChild(js);
var sty = document.createElement('style'); sty.textContent = ress(resp,'css'); html_doc.appendChild(sty);
</script>
Voila, maintenant vous pouvez utiliser le javascript et le css avec les images comme si vous l'avez inclue directement.
J'espère que j'ai été claire :-)