jsPDF addHTML get full contents of scrolling element - javascript

How do I get jsPDF to create an image/pdf from an element that has overflow set so that it has scrollbars. The following example pasted into the addHTML Have a Play page (http://mrrio.github.io/jsPDF/) will only generate a pdf for the section of the div that is showing, even if I choose the "middle" div:
var outer = document.createElement('div');
outer.style.height = "100px";
outer.style.overflow = "scroll";
var middle = document.createElement('div');
for ( var i=0; i<35;i++ ) {
var inner = document.createElement('div');
inner.style.border = "thick solid #0000ff";
inner.style.padding = "10px";
middle.appendChild(inner);
}
outer.appendChild(middle);
document.body.appendChild(outer);
var pdf = new jsPDF('p','pt','a4');
pdf.addHTML(outer,function() {
var string = pdf.output('datauristring');
$('.preview-pane').attr('src', string);
});
(Basically, this is creating a div with a scrollbar, adding a div inside, then adding a whole bunch of divs inside the middle one. There are enough to scroll off screen, so the pdf doesn't pick them up. I thought of popping out a new window, but if I do that, I have to figure out all the different style sheets to pull into the popout.)

Take a look at this discussion: https://github.com/MrRio/jsPDF/issues/270:
I am using addHtml() method with html2canvas.js for making pdf , but for large data table it is not generating pdf ,for short content going fine. Please help me here is my code
To which Flamenco replies:
I started working on a feature to breakup long HTML pages.
Try This:
https://rawgit.com/Flamenco/jsPDF/text-html-table-page-break/examples/html2pdf/test-long-html-table.html
The example code creates a long table and generates a PDF with this. Perhaps his setup is of use to you.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Long Table</title>
</head>
<script src='../../libs/require/require.js'></script>
<script>
require_baseUrl_override = '../../';
require(['../../libs/require/config'], function(){
require(['jspdf.plugin.canvas', 'libs/html2pdf', 'libs/html2canvas/dist/html2canvas', 'libs/saveas'], function(){
var pdf = new jsPDF('p', 'pt', 'a3');
// Enable auto page wrap (there are still margin-top issues...)
pdf.context2d.pageWrapY = pdf.internal.pageSize.height-20;
// create a long table
var table = document.createElement('table');
for (var i=1; i<1000; i++){
var tr=document.createElement('tr');
var td=document.createElement('td');
td.innerHTML = "Item " + i;
tr.appendChild(td);
table.appendChild(tr);
}
document.body.appendChild(table);
// render body to pdf
html2pdf(document.body, pdf, function(){
pdf.save('Test.pdf');
});
}); // require
}); // require
</script>
<body>
</body>
</html>
The code is a bit mangled, but it works.

Related

my createElement(div) is not appearing on my screen, is there something wrong in my javascript code? [duplicate]

Javascript createElement() is not working in Chrome but it works in IE and Firefox fine. Why?
It's working perfectly, use this code:
var catDiv = document.createElement("div");
catDiv.innerHTML = "Test";
document.body.appendChild(catDiv);
Another working example (if you have an element with Id = myTableBody in your HTML)
var appendingTo = document.getElementById("myTableBody");
var tr = document.createElement("tr");
tr.setAttribute("name", "i");
appendingTo.appendChild(tr);
var name = document.createElement("Div" );
will work. And later you can add the attributes like
name.colSpan="2";
document.body.appendChild(name);
Note: don't try to use angular brackets like createElement("<div />").
It will not work in Chrome.
Edit: syntax issue in above code fixed. there should be a dot instead of comma.
Beacause your code is messed up, there's nothing wrong with "createElement":
<html>
<head>
<meta charset = "utf-8">
<title></title>
<script>
window.onload = function () {
for (var i = 0; i < 100; i ++) {
var div = document.createElement ("div");
div.style.border = "1px solid black";
div.style.margin = "20px";
div.style.padding = "10px";
document.body.appendChild (div);
}
}
</script>
<style></style>
</head>
<body></body>
</html>
So I also couldn't get createElement() to work in chrome. After reading Caio's post and testing the code provided I figured out what I was doing wrong.
On w3schools.com the examples they provide always use the tag name in all caps ex. createElement("DIV"), which is the way I was using it and with poor results.
After changing from "DIV" to "div" in my own code it instantly worked.
Thanks Caio.

created element not styling with current JS code

I created an element in JS to be displayed on the html web page. I am not seeing why the styling is not working properly. Maybe someone would be so kind as to point out any error I may have made. Thank you.
///HTML
<!DOCTYPE html>
<html>
<head>
<title>WEB 115 Final Project</title>
</head>
<body>
<script src= "projectJS.js"></script>
</body>
</html>
///JS
var elemH1 = document.createElement("h1");
elemH1.style.color = "red";
elemH1.style.fontFamily = "Tahoma";
elemH1.style.textAlign = "center";
document.write("<h1>Kent Butler</h1>");
var elemH2 = document.createElement("h2");
elemH2.style.fontFamily = "Garamond";
elemH2.style.color = "red";
elemH2.style.fontStyle = "italic";
elemH2.style.textAlign = "center";
document.write("<h2>WEB 115.0001</h2>");
I am looking for the text to styled red and with the specified font families, etc. Thank you.
you need to set the text on your elements and then add them to document.body
var elemH1 = document.createElement("h1");
elemH1.style.color = "red";
elemH1.style.fontFamily = "Tahoma";
elemH1.style.textAlign = "center";
elemH1.innerText = "Kent Butler";
document.body.appendChild(elemH1);
//document.write("<h1>Kent Butler</h1>");
var elemH2 = document.createElement("h2");
elemH2.style.fontFamily = "Garamond";
elemH2.style.color = "red";
elemH2.style.fontStyle = "italic";
elemH2.style.textAlign = "center";
//document.write("<h2>WEB 115.0001</h2>");
elemH2.innerText = "WEB 115.0001";
document.body.appendChild(elemH2);
The problem is that you're creating the element and setting it's properties but you're not actually using them. Instead, you are creating a whole new element without any style attached in document.write("<h1>Kent Butler</h1>")
Also, you should consider putting the styling in a CSS file instead of hard coding it with JS.

Can't load HTML into HTA file when click by link inside of the HTML

I have one HTA file, one JS file is enqueued to the HTA file and HTML files with contents are loaded into the HTA file.
For example this is my_hta_file.hta
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body></body>
</html>
<script type="text/javascript" src="my_js_file.js"></script>
and this is my_js_file.js
function getFileContent(filePath) {
var fileStream = new ActiveXObject('ADODB.Stream');
fileStream.Type = 2;
fileStream.Charset = 'utf-8';
fileStream.Open();
fileStream.loadFromFile(filePath);
var fileContent = fileStream.ReadText();
fileStream.Close();
return fileContent;
}
// initial loading of home page
document.body.innerHTML = getFileContent('index.html');
var pageLinks = document.querySelectorAll('a');
for(i = 0; i < pageLinks.length; i++) {
var linkHref = pageLinks[i].getAttribute('href');
pageLinks[i].setAttribute('href','#!'+linkHref);
// I add this leading prefix to prevent following by the link when click by it
pageLinks[i].onclick = function() {
var page = this.getAttribute('href').substring(3);
if(page == '') {
var page = 'index';
}
// load HTML of the page by link path when click by the link
document.body.innerHTML = getFileContent(page+'.html');
}
}
and my HTML files with contents are:
index.html
Home
Second
Third
<div>Home page content</div>
second.html
Home
Second
Third
<div>Second page content</div>
third.html
Home
Second
Third
<div>Third page content</div>
When I click by a link, I need to load all the HTML content from the HTML file by the link path including the very links I click by.
If I open my HTA file and click the link "Second", I get the second page links and content successfully.
But after that if I click the link "Third", I get the error
Cannot find file 'file:///D:/third' ...
How to resolve the problem?
UPDATE 1
If I move my script to the bottom of the HTA body and add a div for loading HTML for example
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body>
<div id="body"></div>
<script type="text/javascript" src="my_js_file.js"></script>
</body>
</html>
and in my JS file load HTML into div i.e.
document.getElementById('body').innerHTML = ...
instead of
document.body.innerHTML = ...
the problem still remains
As said in the comments, all the links with attached event listeners are replaced by new elements when innerHTML is changed. These new links don't have the listeners which the old elements had.
The snippet below shows how you can use a function to reinit the listeners. The snippet assumes a content wrapper element is used (as you already seem to use it). I've also simplified the code a bit, and used more modern JS (since IE9 mode is used in the OP).
function getFileContent (filePath) {
// As it currently is
}
// Handles clicks on the links
function newContent (e) { // e contains information of the current event
var path = e.target.href || 'index',
body = document.getElementById('body');
e.preventDefault(); // Prevents the default action of the clicked link
body.innerHTML = getFileContent(path + '.html');
init(); // Initialize the new content
return;
}
// Initializes the page
function init() {
var links = document.querySelectorAll('a'),
i, ei;
for (i = 0, ei = links.length; i < ei; i++) {
links[i].addEventListener('click', newContent);
}
return;
}
// Initialize the first page
init();

IE8 display overlap occurs using insertBefore

I'm attempting to move div elements from one section to another using node.insertBefore and order the insertion alphabetically. Upon clicking (in this case clicking A) to reorder I have a problem with elements overlapping as seen in the image below:
The code I'm using to produce this follows; I'm sorry it's a little long, but if you copy it into an html file in it's entirety you'll easily see my problem.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
var moveUp, moveDown;
var moveUp = function() {
var e = window.event.srcElement;
var firstBlock = document.getElementById('firstBlock');
var moved = false;
for (var i=0; i<firstBlock.childNodes.length; i++) {
if (firstBlock.childNodes[i].innerText > e.innerText) {
firstBlock.insertBefore(e, firstBlock.childNodes[i]);
moved = true;
break;
}
if (!moved) firstBlock.appendChild(e);
}
e.onclick = moveDown;
};
var moveDown = function() {
var e = window.event.srcElement;
var secondBlock = document.getElementById('secondBlock');
var moved = false;
for (var i=0; i<secondBlock.childNodes.length; i++) {
if (secondBlock.childNodes[i].innerText > e.innerText) {
secondBlock.insertBefore(e, secondBlock.childNodes[i]);
moved = true;
break;
}
if (!moved) secondBlock.appendChild(e);
}
e.onclick = moveUp;
};
</script>
<title>Test</title>
</head>
<body>
<div id="firstBlock" style="background-color:#dddddd;">
<div onclick="moveDown()">A</div>
<div onclick="moveDown()">B</div>
<div onclick="moveDown()">C</div>
<div onclick="moveDown()">D</div>
</div>
<div id="secondBlock">
<div onclick="moveUp()">E</div>
<div onclick="moveUp()">F</div>
<div onclick="moveUp()">G</div>
<div onclick="moveUp()">H</div>
</div>
</body>
</html>
Am I doing something wrong/odd? Can this be fixed/worked around? Thanks in advance for your help!
Edit:
I can't currently test in any other browsers.
I notice that once one section fills up, the highlighting no longer readjusts itself when items move between sections.
Edit 2: Result of jsfiddle posted by Jared
Happened to come back to this question now. In case anyone else is having this problem, I ended up having to replace the div list with a table and rearrange table rows. Another option may be to use a list.

wanted: simple HTML file that does disclosure triangle <div> hide/reveal

I have a program that produces a text report. I want it to make an HTML report with multiple disclosure triangles, so that when you click a triangle more of the report shows or hides. I am okay with embedding JavaScript inside the file, but I really want it all in a single file, with no additional files. Is there an easy way to do this with modern browsers?
If you don't care about compatibility with Internet Explorer, you could use the html tag: http://www.w3schools.com/tags/tag_details.asp
Its a very quick way to prototype disclosure triangles.
For example:
<details>
<summary>The contents of the summary tag is always visible</summary>
<p>Everything else inside the details tag will be hidden in a disclosure triangle</p>
</details>
The simplest way is something like this:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<style>.wrapper div { display:none;}</style>
<script>
$(function() {
$('.wrapper h2').click(function() { $(this).next().toggle();});
});
</script>
</head>
<body>
<div class="wrapper">
<h2>Example header 1</h2>
<div>bodytext 1</div>
</div>
<div class="wrapper">
<h2>Example header 2</h2>
<div>bodytext 2</div>
</div>
<div class="wrapper">
<h2>Example header 3</h2>
<div>bodytext 3</div>
</div>
</body>
</html>
I have made a simple working example here: http://jsfiddle.net/NXuQt/1/
It isn't pretty but should give you the simple template you need.
Note that in this solution, the entire header is click-able... I figure adding an image and changing it as part of the click event is something you can take care of yoruself, otherwise let me know :)
Note: The javascript is based on the inclusion of the jQuery library.
EDIT: I updated the answer to copy/paste ready working code, the reason you couldn't make it work as it was, was because i had only taken the essentials from the fiddle example. The fiddle automatically ran the click handler initialization at DOMready, which the updated example now has built in :)
With straight HTML, no. That's not what it's for. You will need to use a scripting language, either JavaScript or VBScript, most likely.
This is a script I've used in the past (not mine, but I don't have the URI of the original):
var timerlen = 5;
var slideAniLen = 250;
var timerID = new Array();
var startTime = new Array();
var obj = new Array();
var endHeight = new Array();
var moving = new Array();
var dir = new Array();
function slidedown(objname)
{
if(moving[objname])
return;
if(document.getElementById(objname).style.display != "none")
return; // cannot slide down something that is already visible
moving[objname] = true;
dir[objname] = "down";
startslide(objname);
}
function slideup(objname)
{
if(moving[objname])
return;
if(document.getElementById(objname).style.display == "none")
return; // cannot slide up something that is already hidden
moving[objname] = true;
dir[objname] = "up";
startslide(objname);
}
function startslide(objname)
{
obj[objname] = document.getElementById(objname);
endHeight[objname] = parseInt(obj[objname].style.height);
startTime[objname] = (new Date()).getTime();
if(dir[objname] == "down")
{
obj[objname].style.height = "1px";
}
obj[objname].style.display = "block";
timerID[objname] = setInterval('slidetick(\'' + objname + '\');',timerlen);
}
function slidetick(objname)
{
var elapsed = (new Date()).getTime() - startTime[objname];
if (elapsed > slideAniLen)
{
endSlide(objname)
}
else
{
var d =Math.round(elapsed / slideAniLen * endHeight[objname]);
if(dir[objname] == "up")
d = endHeight[objname] - d;
obj[objname].style.height = d + "px";
}
return;
}
function endSlide(objname)
{
clearInterval(timerID[objname]);
if(dir[objname] == "up")
obj[objname].style.display = "none";
obj[objname].style.height = endHeight[objname] + "px";
delete(moving[objname]);
delete(timerID[objname]);
delete(startTime[objname]);
delete(endHeight[objname]);
delete(obj[objname]);
delete(dir[objname]);
return;
}
function toggleSlide(objname)
{
if(document.getElementById(objname).style.display == "none")
{
// div is hidden, so let's slide down
slidedown(objname);
}
else
{
// div is not hidden, so slide up
slideup(objname);
}
}
You would assign a call to toggleSlide() to the onclick() event of the element you want to toggle.
CSS:
.hidden {
display: none;
}
Javascript:
function createSection(section, hidden) {
var triangle = section.children[0]; // assumes the triangle image is the first child of a section (see HTML)
var contents = section.children[1];
triangle.onclick = function() {
if (contents.className.indexOf("hidden") != -1) { // the section is hidden
contents.className = contents.className.replace("hidden", "");
} else { // the section wasn't hidden
contents.className += " hidden";
}
}
if (hidden) {
contents.className += " hidden";
}
}
// Create the sections when window loads
window.onload = function() {
createSection(document.getElementById("section1"));
createSection(document.getElementById("section2"), true);
}
HTML:
<div id="section1">
<img src="triangle.jpg"></img>
<div>This is the section content</div>
</div>
<div id="section2">
<img src="triangle.jpg"></img>
<div>this section is hidden by default</div>
</div>
Obviously you would have to change some things to your own html file
Well, after some fiddling around, I was able to make a file that does what I want using the switchcontent.js and switchicon.js javascript files I found at http://www.dynamicdrive.com/dynamicindex17/switchcontent2.htm
Here's my code, based on editing down theirs:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dynamic Drive DHTML scripts- Switch Content Script II (icon based)</title>
<script type="text/javascript" src="switchcontent.js" ></script>
<script type="text/javascript" src="switchicon.js"></script>
<style type="text/css">
/* Specifies title style */
.iconspan{
margin: 3px;
cursor:hand;
cursor:pointer;
font-weight: bold;
}
</style>
</head>
<body>
<span id="faqtable1-title" class="iconspan"></span>
How hot is our Sun?<br/>
<div id="faqtable1" class="icongroup2">
The surface of the Sun is around 5800 Kelvin, while the core reaches over 15 million Kelvin.
</div>
<br>
<span id="faqtable2-title" class="iconspan"></span>
How big is our Sun in terms of mass? <br/>
<div id="faqtable2" class="icongroup2">
The contains more than 99.8% of the total mass of our Solar System.
</div>
<script type="text/javascript">
var faqtable=new switchicon("icongroup2", "div")
faqtable.setHeader('▼', '▶') //Set header HTML
faqtable.collapsePrevious(false) //Allow more than 1 content to be open simultanously
faqtable.setPersist(true, 7) //Enable persistence to remember last switch content states for 7 days
faqtable.init()
</script>
</body>
</html>
It looks like this when closed:
▶ How hot is our Sun?
▶ How big is our Sun in terms of mass?
And this when opened:
▼ How hot is our Sun?
The surface of the Sun is around 5800 Kelvin, while the core reaches over 15 million Kelvin.
▼ How big is our Sun in terms of mass?
The contains more than 99.8% of the total mass of our Solar System.

Categories