Save the document generated by javascript - javascript

Javascript can manipulate the document the browser is displaying, so the following:
<script>
document.write("<table><tr><td>Hola</td><td>Adios</td></tr></table>");
</script>
Will make the browser display a table just like if it was the original HTML document:
<table>
<tr>
<td>Hola</td>
<td>Adios</td>
</tr>
</table>
Is there a way I can save/serve this document content?
Currently we have some nicely generated reports using Ext-js, what I would like to do is to have the "text/html" version of it ( I mean, something that doesn't require javascript )
So at the end of the page I would add a button : "Save as blaba" and the document should display the text/plain version.
The only way I could think right now is, to write the content into a javascript variable like:
var content = document.toString(); // or something magic like that.
// post it to the server
Then post that value to the server, and have the server present that value.
<%=request.getParameter("content-text")%>
But looks very tricky.
Is there an alternative?
EDIT
Ok, I almost got it. Now I just need the new window to pop up so the option "would you like to save it shows"
This is what I've got so far
<script>
document.write("<div id='content'><table><tr><td>Hola</td><td>Adios</td></tr></table></div>");
function saveAs(){
var sMarkup = document.getElementById('content').innerHTML;
var oNewDoc = document.open('application/vnd.ms-excel');
oNewDoc.write( sMarkup + "<hr>" );
oNewDoc.close();
}
</script>
<input type="button" value="Save as" onClick="saveAs()"/>
The line:
var oNewDoc = document.open('application/vnd.ms-excel');
Should specify the new content type, but it is being ignored.

Unless its being saved client side with File -> Save Page As..., you will have to do exactly what you are proposing, posting $('body').html() to your server and process it as text.

Here's the upgraded version to open the table contents in .xls format.
<head>
<script>
document.write("<table id='targetTable'><tr><td>Hola</td><td>Adios</td></tr><tr><td>eins</td><td>zwei</td></table>");
function saveAsXLS()
{
var xlObj = new ActiveXObject("Excel.Application");
var xlBook = xlObj.Workbooks.Add();
var xlSheet = xlBook.Worksheets(1);
for (var y=0;y<targetTable.rows.length;y++) // targetTable=id of the table
{
for (var x=0;x<targetTable.rows(y).cells.length;x++)
{
xlSheet.Cells(y+1,x+1)=targetTable.rows(y).cells(x).innerText;
}
}
xlObj.Visible=true;
document.write("The table contents are opened in a new Excel sheet.");//Print on webpage
}
</script>
</head>
<body>
<input type="button" value="Open table in Excel!" onclick="saveAsXLS()"/>
</body>
This code is tested in IE6 and is using ActiveXObject control.
The table I've used here is of order 2x2 and the individual contents are mapped respectively into the excel sheet.
Unlike the .doc version, this does not save the file in client's system. It opens the application with the table content and the client has to save it.
Hope this helps in answering ur question. Lemme know if u face any issues.
Peace.

Depending on your browser support requirements, you could use data URIs
Core for proof of concept (tested in Firefox 3.5.3):
document.write("<div id='content'><table><tr><td>Hola</td><td>Adios</td></tr></table></div>");
function extract(){
return document.getElementById('content').innerHTML;
}
function dataURI(s){
return 'data:application/vnd.ms-excel;base64,' + encode64(s);
}
document.write('open');
I pulled base 64 encode/decode from examples online. Careful: the one I grabbed included a URI encode before base 64 encode that messed me up for a while.

You are getting close to the answer I thinks. The problem is that 'document.open(...)' can only take standard mime-types such as 'text/html', 'text/plain' and a few others
And because of that your code should be:
<script>
document.write("<div id='content'><table><tr><td>Hola</td><td>Adios</td></tr></table></div>");
function saveAs(){
var sMarkup = document.getElementById('content').innerHTML;
var oNewDoc = document.open('text/html');
oNewDoc.write( sMarkup + "<hr>" );
oNewDoc.close();
}
</script>
<input type="button" value="Save as" onClick="saveAs()"/>
Hope this helps.

$(function(){
$('.bbutton').click(function(){
var url='data:application/vnd.ms-excel,' + encodeURIComponent($('#tableWrap').html() )
location.href=url
return false
})
})
.table{background:#ddd;border:1px solid #aaa;}
.table thead th{border-bottom:1px solid #bbb;}
.table tr td{background:#eee;border-bottom:1px solid #fff;
border-left:1px solid #ddd;text-align:center;}
.table tr:hover td{background:#fff;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id='tableWrap'><table style='width:98%;box-shadow:none;' class='table'>
<thead><th>id</th><th>Name</th><th>Address</th></thead>
<tr><td>1</td><td>Jyoti Telecom Services</td><td>http://www.tsjyoti.com</td></tr>
<tr><td>2</td><td>Recharge</td><td>http://recharge.tsjyoti.com</td></tr>
<tr><td>3</td><td>Bhuri Bharaj</td><td>http://bhuribharaj.tsjyoti.com</td></tr>
</table></div>
<p>Your download's ready as Excel Sheet <a href='#'class='bbutton'>Click Here for download</a></p>

If it's just a report, you could use server-side JavaScript to generate it, and then serve it up with whatever MIME type you need...

I dont think that sending your html to the server is a tricky solution. You just have to remember to give a link to your user to download this file. This can be done using a traditional POST, or even using AJAX. It depends on how you want your users to interact if your page.
Using traditional post, you could put all the html content in the value attribute of an input type hidden in your page, named "html_content" or something like that, and when the user clicks in the button "save" you send your user to another page with a link do the file. You send the html to server, a script creates a file in a filesystem with an unique name, and returns a download link.
Using AJAX, you just need to do an AJAX POST passing this variable, and then your script returns a download link, and you dynamically put it in your html - without reloading your page, like it was "only cliente side".
Either way, you'll return a link to the resource you just created in your filesystem with a html extension. Remember to generate unique names in your server for each generated file to avoid collisions.
Beware though that using innerHTML in IE 6 (I dont know if this is a IE family behavior or just about the 6 version) uppercases all tags and removes quotes from attributes. If you're planning to do some post processing in your html, be careful.
I dont know how jQuery or other JS libraries behaves in such situations. I would suggest using it though, they have plenty of browser compatibility checks to abstract all these hacks we use.

Here's my code to save the generated content[client-side] by the JavaScript to the local C: drive in MSWord[.doc] format.
<script>
document.write("<div id='content'><table><tr><td>Holaa</td><td>Adiosa</td></tr></table></div>");
function saveAs()
{
var wordObj=new ActiveXObject("Word.Application");
var docText;
var obj;
var textToWrite = document.getElementById('content').innerHTML;
if (wordObj != null)
{
wordObj.Visible = false;
wordDoc=wordObj.Documents.Add();
wordObj.Selection.TypeText(textToWrite);
wordDoc.SaveAs("C:\\Eureka.doc");
wordObj.Quit();
document.write("The content has been written to 'C:\\Eureka.doc'");//Print on webpage
}
}
</script>
<body>
<input type="button" value="Save in C:" onclick="saveAs()"/>
</body>
I quickly worked on ur issue and came up with this piece of code. Hope I understood your issue correctly.
The contraints in my code are
File format is .doc and not .xls.
Secondly, The file is saved in a static location and not the user specified location[can be optimized].
And, the code uses ActiveX and I didnot check the working in server-side environment.
These need to be addressed in the upcoming versions. (:
Peace.

Is your javascript AJAX which fetches the document.writeln() content from the server, or are you already generating that content when the page is served to the user ? Because if it's the former, I see no reason why you can't save any variables / queries in the session of whatever server-side technology your using and then just generate the plain text stuff from those. Otherwise, you'll have to folow voyager's suggestion above.

Since you're using Ext JS, you probably have a Store object that provides data to the grid? You should be able to extract the data you need by walking through the Store, and then format it the way you want. I don't think scraping the data from the generated HTML is ideal.
Once you grab the data you need from the grid and format it into text, you could POST it to the backend to initiate a download (with Content-Disposition: attachment etc.)
If you're not concerned with being cross-browser, you can also use the data: URL scheme to initiate a download without involving the backend.

This plugin does the job. Tested on IE, FF & Chrome.
https://github.com/dcneiner/Downloadify

Related

Strip HTML elements within DIV

I have a simple search engine on one of our older websites. This site is running IIS 6.0 on Windows Server 2003. The search functionality is provided by Microsoft Indexing Service.
You can see the search functionality on our website. (Just type in "speakers" and you will see some hits.
I would like to use the "FullHit" feature offered by the indexing service. When using this feature the Indexing service inserts the full hit results in between "begindetail" and "enddetail" on a target web page.
The problem that I have is that the documents that are being returned have HTML. This looks messy. (Just click on "Hit Locator Tool" in the search results above to see what I mean.)
I would like to create a DIV section such as ...
<DIV name="target">
begindetail
enddetail
</DIV>
Then, after the page is populated I would like to use javascript to strip out all of the HTML elements (but not the data) between the opening and closing DIV.
For example, <FONT color="magenta">Good Data</FONT> would be modified to only show Good Data.
I can also use Classic ASP if necessary.
Please let me know if you have any suggestions or know of any functions that I can add to the target page to accomplish this task.
Thanks in advance.
I inspected your webpage, and there definitely must be some logic errors in your ASP code. (1) Instead of something like <div></div> being passed to the browser, it is HTML entities for special characters, so it is being passed like &ltDIV&gt &lt/DIV&gt, which is very ugly and is why it is rendering as text instead of HTML code. In your ASP code, you must not be parsing the search result text before passing it to the browser. (2) All of this improperly-formatted code is inserted after the first closing html tag, and then there are closing body and html tags after the improperly-formatted code, so somewhere in your ASP code, you are telling it to append the code to the end of the document, rather than insert it inside the original <body></body>.
If you want to decode the mixture of HTML entities, <br> tags, and text into rendered HTML, this JavaScript may work:
window.onload = function() {
var text = decodeHTMLEntities(document.body.innerText);
document.write(text);
}
function decodeHTMLEntities(text) {
var entities = [
['amp', '&'],
['apos', '\''],
['#x27', '\''],
['#x2F', '/'],
['#39', '\''],
['#47', '/'],
['lt', '<'],
['gt', '>'],
['nbsp', ' '],
['quot', '"']
];
for (var i = 0, max = entities.length; i < max; ++i)
text = text.replace(new RegExp('&'+entities[i][0]+';', 'g'), entities[i][1]);
return text;
}
jsFiddle: https://jsfiddle.net/6ohc1tkr/
But first things first, you need to fix your ASP code, or whatever you use to parse and then display the search results. That's what is causing the improper formatting and display of the HTML. Show us your back-end code and then we can help you.
This is what I used to accomplish what you are trying to do.
string-strip-html
It worked pretty well for me.
I now have the search feature working as expected. I would like to thank everyone for their insightful comments. This feedback helped me identify and fix the problem.
OS: Windows Server 2003
IIS: 6.0
Microsoft Index Server
The hit locator tool will only work properly for HTML pages. If you use this tool with a simple TXT file then the results will not be displayed correctly.

Change <div> background image with javascript

I've this in my html file
<div class="change">
<div id="changed" onclick="change_DImage()">New Upload...</div>
<input id="browse" type="file" onchange="ImagLoc()">
</div>
and this in javascript file
function change_DImage(){
document.getElementById("browse").click();
}
function ImagLoc(){
var x = (document.getElementById("browse").value).toString();
var ImgId = x.substr(12,6);
var NewImg = "url('./image/MyAlbum/" + ImgId + "')";
document.getElementById("dailyPic").style.backgroundImage = NewImg;
}
it's work pretty well but when I refresh my browser it'll change back to the default
for this in css file
background-image: url("../image/smokebird.jpg");
On page reload obviously image is going to reset to the original image. To keep it as it is even after page refresh you can do,
Save the image in Cookie (base 64 format), but there is a size limit since you can save small size images only.
On image select, you can save the image file remotely on your server asynchronously (using AJAX) and you can recall the image using the server session.
Javascript manipulates the only current state of the Html, not the file on server side. To handle it, you have to store state on server side, and change it both client and server side on button click.
Storing changed value on browser's cookie or local storage, and get stored one on page load is another option.
localStorage example:jsfiddle
However localStorage can be easily cleaned by user, even by mistake. I have found this answer useful about how it can be cleaned: SO link. Other drawback (if your really care about it) is a need of use Inline styling. There is attr css function but other than content usage is currently limited so I would stick to Inline styling.
I made more understandable version including your code, here:
jsfiddle, however I am not sure what this line and function suppose to do so I have removed it:
<div id="changed" onclick="change_DImage()">New Upload...</div>
Edit:
obviously second jsfiddle code will not work on jsfiddle, you need to inject it to your code.

Changing embed src attribute dynamically using file dialog

I implemented a HTML page which runs locally on a Linux machine (using the most current firefox versions). It is used to embed a plugin which I have programmed.
At the moment, I statically pass a file path, the plugin has to load, that is hard-coded in the HTML file:
<embed id="embed1" type="application/x-bbx" src="/tmp/testfile.bbx"></embed>
The HTML page is generated for all .bbx files. I'm currently trying to figure out how I can avoid the hard-coded path by adding an <input type="file"> element. The aim is to dynamically change the loaded file (specified by src) to avoid the need of generating the HTML page for all .bbx files.
As browsers do not allow access to the file path: how I can change the embed's source according to the loaded file?
For several technical reasons, I would like to avoid using JQuery. Also note, that the page is run solely locally by specific users.
EDIT 1: The plugin is scriptable, i.e. I can invoke functions on and pass parameters to the plugin using JavaScript. Thus, it would suffice to get the whole file path and pass it to the plugin which in turn does the rest internally.
EDIT 2: For clarification: I want to avoid the burden of having the user enter the file path manually, which is why I intended to use <input type="file">
var Target = "/tmp/testfile2.bbx";
var Source = document.getElementById('embed1');
var Clone = Source.cloneNode(true);
Clone.setAttribute('src',Target);
Source.parentNode.replaceChild(Clone,Source);
But history of browser gets no event here... so .back() will work incorrectly.
Thats how I got here today. Hope this helps. And sorry if a was not fluxed to the right moment. ;-)
If I understood right, this should do it!
<script>
var embed1 = document.getElementById('embed1');
embed1.src = 'your path';
</script>
Here is a complete example:
JSFiddle
<input type="text" id="path" name="path" />
<input type="submit" id="submit" value="Change it" onclick="changePath()">
<embed id="embed1" type="application/x-bbx" src="/tmp/testfile.bbx"></embed>
<script>
function changePath() {
var e = document.getElementById('path');
var val = e.value;
var embed1 = document.getElementById('embed1');
embed1.src = val;
}
</script>

Saving an edited SVG file as a new file or to DB

I don't often need to ask questions but Google has failed me this time
so I have a site that uses Javascript to edit an external SVG file like so:
<embed id="svgFile" src="svgFile.svg" type="image/svg+xml" />
I have a form with inputs to edit the SVG on the fly with Javascript and Jquery like so:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="JavascriptFile.js"></script>
....HTML....
<input id="txt1" name="text_one" maxlength="16" type="text" class="text" placeholder="Line one" onkeyup="update(1)" />
the javascript is something like this:
function update(n) {var txtID = n;
var txt = document.getElementById("txt" + txtID).value;
var svgTXT = document.getElementById("svgFile").getSVGDocument().getElementById("txt" + txtID);
svgTXT.textContent = txt;
}
Now this all works OK and the "image"/SVG updates on the page BUT now I need to save this updated image.
New I don't know exactly what file format we need but saving the information to a php/MySQL DB and PDF are a minimum. the PDF is for the user to save and print... what ever they want to do and the DB is for on-line saving.
I also have JQuery linked to the site but I find Javascript more natural to code in, ether way I need some sort of solution/example/plugin. Can anyone help!?
I accomplished this by using the following code segments in php and mySQL database :
First of all, remember svg is basically stored in text just like HTML is also. And svg tags, all be it different ones, are laid out very similar to HTML tags.
Storing into the database. You must use the following code segment in the actual mySQL Insertcall. I found out if you do this to the variable first and then put the variable in the insert call it will not work. The function must be in the mySQL statement.
mysql_real_escape_string($myValue)
Retrieving Into textbox in value. Assuming your values have been already retrieved from the database and now are in an array Called theValues. Basically I am Removing any backslashes but before hand I'm making sure it can be displayed correctly using htmlentities. Since you are no Backslashes in svg that I know of it fixes it where servers replace quotes with \". If you do encounter some Backslashes in svg you'll just have to be a bit more clever in your replacement function.
$myValue= str_replace("\\", "", htmlentities($theValues->myValue));
echo $myValue;
echoing out on to a page same reasons as above, but the htmlentities function Makes it only display the text of the svg Instead of processing the svg And displaying your picture. this is only required for displaying svg after the text of the Has been stored in a data base but it will not hurt your display If it wasn't the data the first, just A needless function call .
str_replace("\\", "",$myValue)
Saving as SVG
Use XMLSerializer to get a source-XML representation of your SVG, and post that back to your server (using AJAX if you like).
Saving as a PNG
Use XMLSerializer to create a data URI for your SVG, and use that as the source for an <img> element. Draw this image to an HTML5 canvas and then use toDataURL() to convert the contents to a base64-encoded PNG data URI, whichh you can then post to your server and save as a file.
Caveat: The current version of Chrome and semi-recent versions of Firefox (but not the latest) currently "punt" on security and taint the canvas when you draw any SVG, preventing you from getting a data URI.
Note: Both answers above require IE9+; but then, that's true for SVG, too.

Getting content of a script file using Javascript

I have the following script element in my web page:
<script src="default.js" type="text/javascript"></script>
Using JavaScript, I want to be able to retrieve the content of the script file. I know I could use an ajax request to get the data but then I am getting something from the server that I already have locally.
So what I would prefer to do is retrieve the content from the DOM (if that's possible) or something that has the same result.
Cheers
Anthony
UPDATE
I was trying to simplify the question, maybe a bad a idea, I thought this way would cause less questions.
The real situation I have is as follows, I actually have
<script type="text/html" class="jq-ItemTemplate_Approval">
...
html template that is going to be consumed by jQuery and jTemplate
...
</script>
Now this works fine but it means each time the page loads I have to send down the template as part of the HTML of the main page. So my plan was to do the following:
<script src="template.html" type="text/html"></script>
This would mean that the browser would cache the content of template.html and I would not have to send it down each time. But to do this I need to be able to get the content from the file.
Also in this case, as far as I know, requesting the content via ajax isn't going to help all that much because it has to go back to the server to get the content anyway.
If I understand you correctly, you don't want to use Ajax to load an html template text, but rather have it loaded with the rest of the page. If you control the server side, you can always include the template text in an invisible div tag that you then reference from Javascript:
<div id="template" style="display:none;">
...template text...
</div>
<script>
// pops up the template text.
alert(document.getElementById("template").innerHTML);
</script>
If you are just looking for to load the template so that you can have it cached, you can put the contents in a variable like this:
<script>
var template = "template text..";
</script>
or you can load it using ajax and store the template in a variable so it is accessible. It's pretty trivial in jquery:
var template;
$.get("template.html", function(data){
template = data;
});
unless you load a script as literal text in the page, it does not exist as text. It is interpreted by the browser and melded into the runtime, with any other scripts.
If you want the source you have to fetch it again,if with Ajax get the responseText.
It will come from the browser cache, and doesn't have to be downloaded again.
I think what you want to do is to assign a variable inside template.js. Then you have the variable available for use wherever you want in jquery. Something like:
var tpl = "<div> ... </div>"
Wouldn't this be a simpler solution to your problem? We do this in Ext JS. I think this will work for you in jQuery.
You could get the attribute of the src of the script and then use XHR to get the contents of the JS file. It's a much cleaner way of doing it IMO. e.g.:-
if(window.XMLHttpRequest) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.status == 200 && xhr.readyState == 4) {
var sourceCode = xhr.responseText;
alert('The source code is:-\n'+sourceCode);
}
}
xhr.open("GET",document.getElementById('scriptID').src,true);
xhr.send(null);
}
Using an iFrame & HTML5 Local Storage
Save the templates for rendering later...
not stoked about the iFrame, but it seems to be working pretty good (haven't ran performance tests yet)
Put the iFrame on the page you want the template on (index.html)
<html>
<head>
<iframe src="mustache.Users.html" onload="this.remove();" class="hidden" id="users_template"></iframe>
</head>
</html>
Make sure the src attribute is set
hide the element until you can get rid of it after it loads
Put this body wrapper around your template (mustache.Users.html)
(don't worry it won't show up in the template)
<body onload="localStorage.setItem('users_template',this.document.body.innerHTML);">
<ul class="list-group" id="users" >
{{#users}}<li>{{name}}</li>{{/users}}
</ul>
</body>
replace 'users_template' with whatever name for your variable
the 'onload' attribute saves the template into localStorage during load
Now You can access your templates from anywhere
localStorage.getItem('users_template')
OR
window.localStorage.getItem('users_template')
What is in the JavaScript file? If it's actual code, you can run functions and reference variables in there just like you had cut and paste them into the webpage. You'll want to put the include line above any script blocks that reference it.
Is this what your looking to accomplish?
Why not use Ajax (well Ajah because its html :-))?
when the server is set up correctly and no no-cache or past expires headers are sent, the browser will cache it.
The way that most JavaScript import files work is they include a script, that immediately calls a function with a parameter of certain text, or of another function. To better illustrate, say you have your main index.html file, set it up like this:
<html>
<head>
</head>
<body>
<script>
let modules = {};
function started(moduleName, srcTxt) {
modules[moduleName] = (srcTxt) //or something similar
}
</script>
<!--now you can include other script tags, and any script tags that will be included, their source can be gotten (if set up right, see later)-->
<script src="someOtherFile.js"></script>
</body>
</html>
now make that other file, someOtherFile.js, and right away when its loaded, simply call that "started" function which should already be declared in the scope, and when thats done, then whatever text is passed, from the file, is stored in the main index.html file. You can even stringify an entire function and put it in, for example:
started("superModule", (function() {
/*
<?myCustomTemplateLanguage
<div>
{something}Entire Javascript / html template file goes here!!{/something}
</div>
?>
*/
}).toString());
now you can access the inner content of the function, and get all the text in between the comments, or better yet, then do other parsing etc, or make some other kind of parsing identifiers at the beginning and end of the comments, as shown above, and get all text in between those

Categories

Resources