rnd me
06-21-2007, 09:45 PM
This function will produce a URL that appears to be a file.
There are two versions:
1. a 500-pound gorilla version that accepts almost anything as input.
2. a lightweight version that turns strings into virtual HTML files.
First I'll mention the one major drawback: IE doesn't recognize data urls (http://en.wikipedia.org/wiki/Data:_URI_scheme) yet.
For a Live Demo, paste this into your addressbar and click go. (press back to return).
data:text/html;charset=utf-8;base64,PGI+aGVsbG8gd29ybGQ8L2I+
//output of: dataUrl("<b>hello world<\/b>", "text\/html")
With that out of the way, here's the code:
function dataUrl(data, mimeType){ // turns a string into a url that appears as a file. (to ff/op/saf)
encType= (!!btoa) ? ";base64" : "";
var esc = (!!encType) ? function(d){return btoa(d);} : function(d){return escape(d);};
if(!mimeType){mimeType= (data.nodeName) ? "text\/html" :"text\/plain";};
b="data:"+mimeType+";charset="+document.characterSet+"+encType+",";
if ("string number date boolean function".indexOf(typeof data) > -1){ b+=esc(data.toString()); return b; };
if ( data.constructor==Array){b+= esc( data.join("") ); return b; };
if(typeof data=="xml"){b+=esc(data.toSource()); return b;} //FF2 xml frag/doc
//for more complicated data, attempt to determine the format.
if(typeof data=="object"){
if(!!data.value && !!data.value.length){b+=esc(data.value); return b;}; //input tags w/content
if(!!data.innerHTML){b+=esc(data.innerHTML); return b;} //HTML tag
if(!!data.length){ //weird stuff like nodelists
var G=function(ob){r=[]; i=0;
for(i;i<ob.length;i++){
if(dataUrl(ob)) r=dataUrl(ob[i]);} return r.join("\n");};//end g
return (b+G(data));}//end if object w/length
if(!! eval(data.toSource()) ){b+=esc(data.toSource()); return b;}; //JSON
}//end if object
return;
} //end function dataUrl
function dataUrlStr(data){ return ("data:text\/html,"+escape(data));}
Usage: dataUrl(data, mimeType)
data- The desired contents of the file
mimeType- The type of content you want the browser to see.
output: An encoded string representation of the file; an href.
The output 'file' could be any text-based file format, depending upon what you set mimeType to be:
-HTML document (yawn) (text/html)
-Rss feed (text/xml)
-M3U playlist (audio/mpegurl)
-Excel spreadsheet, CSV (application/vnd.ms-excel)
-JavaScript (text/javascript)
-StyleSheet (text/css)
- You get the idea...
Input Details:
-Can accept [I]almost any javascript type: strings, numbers, arrays (which it will flatten), nodes, node lists, xml objects in FF2, functions (for which it outputs the source code), complex JSON objects, and dates. (whew, I think that's all of 'em...)
-if you want to output an element as html, or anything else as text, you can skip the mimeType argument.
Notes:
-You will most likely want to assign the output to a link href or the .scr of a script, stylesheet, or iframe, or to window.location.href.
-If you assign it to an iframe or object, it will load immediately.
-assigning it to a (<a>) tag will let you 'right-click, SaveAs' the file.
-clicking the link will open the 'file' in the browser just like a regular file.
-output an html document that has scripts, and they execute immediately.
-the cool thing about this is that the script will have a clean context. (no global variables from the parent).
-if used in an iframe- it can push to main page via window.top .
-if used in with an <object>, it will be completely private.
Caveats:
-doesn't work with IE yet.
-'saving As' doesn't offer a default file extention.
-there is 2kb limit for safari and opera URLs.
-search engines cannot see the links.
-XmlHTTP Requests from within usually don't work.
Examples:
To save my fingers, I will utilize the follow shortcut functions in these examples:
function el(tid) {return document.getElementById(tid)};
function tags(tid) {return document.getElementsByTagName(tid)};
//test
tags("a")[0].href=dataUrlStr("<b>Hello World!<\/b>")
//make a 2D array into an Excel SpreadSheet - (works with 1D lists also)
var grades= [["Subject" , "Grade"],
["Math" , "A" ],
["English", "B+" ],
["Gym", "C" ],
["Art", "A-" ],
["Science", "A+" ] ]
var exl=grades.join("\n").toString().replace(/,/g , "\t")
window.location.href=dataUrl(exl, "application/vnd.ms-excel")
//note: if data contains commas: loop through main, .join('\t') each index.
//execute script in a fresh enviroment:
window.testme="123456789"; //make a new global
var testJs="<script>alert('hidden window.testme='+ window.testme )<\/script>";
var fr= document.createElement("iframe");
fr.id="hiddenframe";
fr.style.display='none';
document.body.appendChild(fr); //add a hidden frame
alert("main window.testme="+window.testme);
el("hiddenframe").src=dataUrlStr(testJs);
//re-using the above example, pass existing functions to the hidden frame, and return the result.
var tJs="<script>";
tJs+= [tags, el].join("\n"); //bundle a couple functions
tJs+= "\n alert('hidden window has '+tags('*').length)"
tJs+= "<\/script>";
el("hiddenframe").src=dataUrlStr(tJs)
//open a playlist
var plTxt="#EXTM3U\n#EXTINF:202,Minuet in G\nhttp:\/\/www.mfiles.org.uk\/downloads\/beethoven-minuet-in-G.mp3"
el("hiddenframe").src=dataUrl(plTxt, "audio/mpegurl"
//open all the 'code' on this page as a plain text document.
function ob2Array(ob){var r=[]; for(var z=0; z<ob.length;z++){r[z]=ob[z]};return r};
function group( List, f) //applies a function (f) to an array and returns result...
{var z=0; Ray=[]; len=List.length;for (z;z<len;z++){Ray[Ray.length]=f(List[z]); }
return Ray;};
var codes=group(ob2Array(tags("pre")), function(x){if(x.className=="alt2")return x.textContent});
window.location.href=dataUrl(codes)
//make this thread into an rss feed
function tag(nd, tx){ return ["<",nd,">",tx,"<\/",nd,">"].join("")}
function dp (s) {var d = new Date();d.setTime(Date.parse(s)); return d.toUTCString()}
var X=PHP.htmlspecialchars
var chan=[]; var y = new Date();
chan[0]=tag("title", "CodingForums.com");
chan[1]=tag("link", window.location.href);
y.setTime(ajax_last_post+"000")
chan[2]=tag("pubDate", y.toUTCString())
chan[3]=tag("link", "http:\/\/www.codingforums.com\/")
var codes=Group(ob2Array(tags("table")), function(x){
var i=[];d=""; p=d; t=d; l=d;j=d;a=0;
if(x.id.substr(0,4)=="post"){
p=tag("pubDate", dp(x.rows[0].cells[0].textContent.replace(/-/g, "\/")));
t=tag("title", document.title)
l=tag("link", "http:\/\/www.codingforums.com\/showpost.php?p="+tags("table")[5].id.substr(4))
ta=x.rows[1].cells[0].getElementsByTagName('a')[0]
a="<author>"+ta.href+" ("+ta.textContent+") <\/author>";
d=X(x.rows[1].cells[1].textContent.toString())
j=[d,t,p,l,a].join("\n");
return tag('item', j)
}//end if
});
tags("a")[2].href=dataUrl(tag("channel", chan.join("\n") + codes), "text\/xml")
So, i think that should be enough examples to get going.
[I]"The only limitation is your imagination"
There are two versions:
1. a 500-pound gorilla version that accepts almost anything as input.
2. a lightweight version that turns strings into virtual HTML files.
First I'll mention the one major drawback: IE doesn't recognize data urls (http://en.wikipedia.org/wiki/Data:_URI_scheme) yet.
For a Live Demo, paste this into your addressbar and click go. (press back to return).
data:text/html;charset=utf-8;base64,PGI+aGVsbG8gd29ybGQ8L2I+
//output of: dataUrl("<b>hello world<\/b>", "text\/html")
With that out of the way, here's the code:
function dataUrl(data, mimeType){ // turns a string into a url that appears as a file. (to ff/op/saf)
encType= (!!btoa) ? ";base64" : "";
var esc = (!!encType) ? function(d){return btoa(d);} : function(d){return escape(d);};
if(!mimeType){mimeType= (data.nodeName) ? "text\/html" :"text\/plain";};
b="data:"+mimeType+";charset="+document.characterSet+"+encType+",";
if ("string number date boolean function".indexOf(typeof data) > -1){ b+=esc(data.toString()); return b; };
if ( data.constructor==Array){b+= esc( data.join("") ); return b; };
if(typeof data=="xml"){b+=esc(data.toSource()); return b;} //FF2 xml frag/doc
//for more complicated data, attempt to determine the format.
if(typeof data=="object"){
if(!!data.value && !!data.value.length){b+=esc(data.value); return b;}; //input tags w/content
if(!!data.innerHTML){b+=esc(data.innerHTML); return b;} //HTML tag
if(!!data.length){ //weird stuff like nodelists
var G=function(ob){r=[]; i=0;
for(i;i<ob.length;i++){
if(dataUrl(ob)) r=dataUrl(ob[i]);} return r.join("\n");};//end g
return (b+G(data));}//end if object w/length
if(!! eval(data.toSource()) ){b+=esc(data.toSource()); return b;}; //JSON
}//end if object
return;
} //end function dataUrl
function dataUrlStr(data){ return ("data:text\/html,"+escape(data));}
Usage: dataUrl(data, mimeType)
data- The desired contents of the file
mimeType- The type of content you want the browser to see.
output: An encoded string representation of the file; an href.
The output 'file' could be any text-based file format, depending upon what you set mimeType to be:
-HTML document (yawn) (text/html)
-Rss feed (text/xml)
-M3U playlist (audio/mpegurl)
-Excel spreadsheet, CSV (application/vnd.ms-excel)
-JavaScript (text/javascript)
-StyleSheet (text/css)
- You get the idea...
Input Details:
-Can accept [I]almost any javascript type: strings, numbers, arrays (which it will flatten), nodes, node lists, xml objects in FF2, functions (for which it outputs the source code), complex JSON objects, and dates. (whew, I think that's all of 'em...)
-if you want to output an element as html, or anything else as text, you can skip the mimeType argument.
Notes:
-You will most likely want to assign the output to a link href or the .scr of a script, stylesheet, or iframe, or to window.location.href.
-If you assign it to an iframe or object, it will load immediately.
-assigning it to a (<a>) tag will let you 'right-click, SaveAs' the file.
-clicking the link will open the 'file' in the browser just like a regular file.
-output an html document that has scripts, and they execute immediately.
-the cool thing about this is that the script will have a clean context. (no global variables from the parent).
-if used in an iframe- it can push to main page via window.top .
-if used in with an <object>, it will be completely private.
Caveats:
-doesn't work with IE yet.
-'saving As' doesn't offer a default file extention.
-there is 2kb limit for safari and opera URLs.
-search engines cannot see the links.
-XmlHTTP Requests from within usually don't work.
Examples:
To save my fingers, I will utilize the follow shortcut functions in these examples:
function el(tid) {return document.getElementById(tid)};
function tags(tid) {return document.getElementsByTagName(tid)};
//test
tags("a")[0].href=dataUrlStr("<b>Hello World!<\/b>")
//make a 2D array into an Excel SpreadSheet - (works with 1D lists also)
var grades= [["Subject" , "Grade"],
["Math" , "A" ],
["English", "B+" ],
["Gym", "C" ],
["Art", "A-" ],
["Science", "A+" ] ]
var exl=grades.join("\n").toString().replace(/,/g , "\t")
window.location.href=dataUrl(exl, "application/vnd.ms-excel")
//note: if data contains commas: loop through main, .join('\t') each index.
//execute script in a fresh enviroment:
window.testme="123456789"; //make a new global
var testJs="<script>alert('hidden window.testme='+ window.testme )<\/script>";
var fr= document.createElement("iframe");
fr.id="hiddenframe";
fr.style.display='none';
document.body.appendChild(fr); //add a hidden frame
alert("main window.testme="+window.testme);
el("hiddenframe").src=dataUrlStr(testJs);
//re-using the above example, pass existing functions to the hidden frame, and return the result.
var tJs="<script>";
tJs+= [tags, el].join("\n"); //bundle a couple functions
tJs+= "\n alert('hidden window has '+tags('*').length)"
tJs+= "<\/script>";
el("hiddenframe").src=dataUrlStr(tJs)
//open a playlist
var plTxt="#EXTM3U\n#EXTINF:202,Minuet in G\nhttp:\/\/www.mfiles.org.uk\/downloads\/beethoven-minuet-in-G.mp3"
el("hiddenframe").src=dataUrl(plTxt, "audio/mpegurl"
//open all the 'code' on this page as a plain text document.
function ob2Array(ob){var r=[]; for(var z=0; z<ob.length;z++){r[z]=ob[z]};return r};
function group( List, f) //applies a function (f) to an array and returns result...
{var z=0; Ray=[]; len=List.length;for (z;z<len;z++){Ray[Ray.length]=f(List[z]); }
return Ray;};
var codes=group(ob2Array(tags("pre")), function(x){if(x.className=="alt2")return x.textContent});
window.location.href=dataUrl(codes)
//make this thread into an rss feed
function tag(nd, tx){ return ["<",nd,">",tx,"<\/",nd,">"].join("")}
function dp (s) {var d = new Date();d.setTime(Date.parse(s)); return d.toUTCString()}
var X=PHP.htmlspecialchars
var chan=[]; var y = new Date();
chan[0]=tag("title", "CodingForums.com");
chan[1]=tag("link", window.location.href);
y.setTime(ajax_last_post+"000")
chan[2]=tag("pubDate", y.toUTCString())
chan[3]=tag("link", "http:\/\/www.codingforums.com\/")
var codes=Group(ob2Array(tags("table")), function(x){
var i=[];d=""; p=d; t=d; l=d;j=d;a=0;
if(x.id.substr(0,4)=="post"){
p=tag("pubDate", dp(x.rows[0].cells[0].textContent.replace(/-/g, "\/")));
t=tag("title", document.title)
l=tag("link", "http:\/\/www.codingforums.com\/showpost.php?p="+tags("table")[5].id.substr(4))
ta=x.rows[1].cells[0].getElementsByTagName('a')[0]
a="<author>"+ta.href+" ("+ta.textContent+") <\/author>";
d=X(x.rows[1].cells[1].textContent.toString())
j=[d,t,p,l,a].join("\n");
return tag('item', j)
}//end if
});
tags("a")[2].href=dataUrl(tag("channel", chan.join("\n") + codes), "text\/xml")
So, i think that should be enough examples to get going.
[I]"The only limitation is your imagination"