I'm trying to use HTML2Canvas with jsPDF to save some accordions to the pdf. Accordions are created dynamically with javascript and i'm trying to get their height to save them to pdf (i need to split the page at some point and save them in separate images because they're way too big). I've gathered all the accordions with their classname:
function gatherAccordions(){
//Launched on button click
var accordionArr = document.getElementsByClassName("akkordion");
for (var i = 0; i<accordionArr.length;i++){
console.log(accordionArr[i]);
console.log(accordionArr[i].clientHeight); //returns 0
}
}
Edit: as i read a bit more i got that .clientHeight will return 0 in case height is not set in CSS. I decided to try the jQuery approach which was highly suggested. Although it returned me -2 (which obviously can't be the right height).
function gatherAccordions(){
var accordionArr = document.getElementsByClassName("akkordion");
for (var i = 0; i<accordionArr.length;i++){
console.log(accordionArr[i]);
console.log($("#"+accordionArr[i].id).height()); //returns -2
}
}
Any ideas how could I approach this thing? I have to note that the accordions (as you can see from code below) are not the bottom elements of the accordion tree, there are several divs and other stuff below it. If i gave .height() to accordionBody and accordionhead separately i did recieve -20 and -31 as a result height, which also sounds weird (being negative). Also, when i added elements to the accordion body then the height of body did not increase although visually i can clearly tell that it did.
This builds the accordions:
/*
#Builds the head of accordion which contains main stats
*/
function buildAccordionHead(player){
//player has attributes: coef, ratio, pos, hasplayed, name, points
//This is the panel that holds the player main information (coef,name,pos etc)
var accordionHead = document.createElement("div");
accordionHead.className = "panel-heading";
accordionHead.dataset.parent = "#accordion";
accordionHead.dataset.toggle = "collapse";
accordionHead.setAttribute('href', "#id_"+player.pos);
//This is the container for positioning items
var container = document.createElement("div");
container.className = "container-fluid";
//Create playerrow (FN06)
var upper_row = rowCreate("KOHT","","K","S","P",true);
var playerRow = rowCreate(player.pos,player.name,player.coef,player.ratio,player.score,false);
//Add row(s) to the children of container
container.appendChild(upper_row);
container.appendChild(playerRow);
//Add container to the children of accordion head
accordionHead.appendChild(container);
return accordionHead;
}
/*
Builds the body of the accordion which contains history
*/
function buildAccordionBody(player,round){
//moving inside out!
//generates container-fluid element with a rows inside
if (even){
var containerfluid = historyRowEven(player);
}
else{
var containerfluid = historyRowOdd(player,round);
}
var bodyel = document.createElement("div");
bodyel.className = "panel-body";
bodyel.appendChild(containerfluid);
var collapser = document.createElement("div");
collapser.id = "id_"+player.pos;
collapser.className = "panel-collapse collapse";
collapser.appendChild(bodyel);
return collapser;
}
/*
The main builder function!
*/
function buildAccordion(player,round){
//This is outer panel
var accordionPanel = document.createElement("div");
accordionPanel.className = "panel panel-default akkordion";
var accordionHeading = buildAccordionHead(player);
var accordionBody = buildAccordionBody(player,round);
//Add accordion head to the children of accordion-panel
accordionPanel.appendChild(accordionHeading);
accordionPanel.appendChild(accordionBody);
accordionPanel.id = "collapser_id_"+player.pos;
//Add accordion-panel to the children of div with accordion
var mainElement = document.getElementById("accordion");
mainElement.appendChild(accordionPanel);
}
Related
I'm trying to make the elements on the page fade in on scroll. Easy enough right? Not for me.
HTML is a standard list.
CSS sets all elements to opacity 0 prior to scrolling.
I'm trying to use Native JavaScript only.
// get current page body
var actBody = document.getElementById('acts-body');
// on scroll function
actBody.onscroll = function(){
// get screen height
var screenPosition = window.innerHeight;
// get all text elements
var artistName = document.getElementsByClassName('artist');
// loop through all elements
for(var i = 0; i < artistName.length; i++){
// get each elements position from top
var positionFromTop = artistName[i].getBoundingClientRect().top;
// if element is in viewport add class
if(positionFromTop - screenPosition <= 0){
artistName[i].classList.add('txt-fadeIn');
}
else{
artistName[i].classList.remove('txt-fadeIn');
}
console.log(artistName[i]);
}
i think it should solve it
if(screenPosition - positionFromTop <= 0){
artistName[i].classList.add('txt-fadeIn');
}
H! Guys
First of all, excuse me for my bad english (I'm working on it). Second: I don't know anything about JavaScript and copy this codes piece by peace. So be patient and listen to my situation please.
I have a svg map and when you click on each sectoin, a box will appear and show the region's name and region's evaluation. I already solve the region's name part with:
for (var i = 0; i < regions.length; i++){
.... some line codes ....
$infobox.find('.infobox_title').text(this.data('region_name'));
.... some line codes ....
Now I want to grab Evaluation's value from a csv file that loads to page using:
function loadFile(event) {
alasql('SELECT * FROM FILE(?,{headers:true})',[event],function(data){
var myseries = [];
Object.keys(data[0]).forEach(function(key){
var ds = data.map(function(d){ return +d[key];});
myseries.push({name:key,data:ds});
});
});
}
I'm sure the data is loaded to page, cuz I checked in console log:
console.log(key);
console.log(ds);
And my csv file is something like this:
regions,evaluation
1,90
2,80
...
22,70
Pleas tell me How can I grab the evaluation numbers that loaded to the page and replace it in place of "Evaluation's place" ???
Take a look at snapshot for clearity:
You can try this code to put labels on top of image.
First, prepare the image with the map in HTML and cover it with container DIV element:
<div id="container">
<img src="map.jpg" style="position:absolute; top:0px; left:0px;"/>
</div>
Then create the new label element, add style properties (position, content, color, etc.) and append it to container on top of it (look at the "position:absolute" style element):
var container = document.getElementById('container');
// Create new element dinamically
var lb = document.createElement('div');
lb.innerHTML = '<b>'+d.regionid+'</b><br/>'+d.evaluation;
lb.style.position = "absolute";
lb.style.left = regions[d.regionid-1].x+"px";
lb.style.top = regions[d.regionid-1].y+"px";
// Append new element to container
container.appendChild(lb);
See the working snipped below or in jsFiddle
Comments:
I did not include the reading CSV code in the example (because you already loaded it).
The example does not use d3.js library.
Please, comment if these conditions are important.
var data = [
{regionid:1,evaluation:90},
{regionid:2,evaluation:80},
{regionid:3,evaluation:70},
{regionid:4,evaluation:60},
{regionid:5,evaluation:50},
{regionid:6,evaluation:40},
{regionid:7,evaluation:30},
];
var regions = [
{x:110,y:100},
{x:220,y:100},
{x:250,y:180},
{x:250,y:230},
{x:290,y:220},
{x:150,y:160},
{x:350,y:180},
];
var container = document.getElementById('container');
for(var i=0; i<data.length; i++) {
var d = data[i];
var lb = document.createElement('div');
lb.innerHTML = '<b>'+d.regionid+'</b><br/>'+d.evaluation;
lb.style.position = "absolute";
lb.style.left = regions[d.regionid-1].x+"px";
lb.style.top = regions[d.regionid-1].y+"px";
lb.style.backgroundColor = "white";
lb.style.textAlign = "center";
container.appendChild(lb);
};
<div id="container">
<img src="https://pbs.twimg.com/media/B8woY_DCMAEojTy.jpg" style="position:absolute; top:0px; left:0px;"/>
</div>
I am trying to animate a dynamically created div with javascript, the id for the div is assigned when it is created, everything works fine until I attempt to animate one of the divs, I am trying this :
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
I know this is supposed to move the div infinitely to the left. However nothing happens at all and I cannot figure out why, I don't think its the fact that I dynamically create the divs as I have checked all the Id's and they all exist so I don't think its because it can't find Id0, but just incase here is a snippet of my div creation code :
for(var i=0; i<ca.length; i++)
{
var c = ca[i].trim();
var start = c.indexOf('"coursename":"') + 14;
var end = c.indexOf('","coursemark":"');
var CC = c.substring(start,end);
var start = c.indexOf('","coursemark":"') + 16;
var end = c.indexOf('%"')+1;
var CM = c.substring(start,end);
var idCount = i;
var div = document.createElement("div");
div.style.width = "180px";
div.style.height = "75px";
div.style.backgroundColor = "rgba(0,100,175,0.8)";
div.style.color = "white";
div.style.marginTop = "2%";
div.style.marginLeft = "50%";
div.id = "sortID"+idCount;
div.innerHTML = "Course Name : " + CC + " Course Mark : " + CM + " Id : " + div.id;
document.body.appendChild(div);
}
This code works fine however and creates the divs perfectly, I just can't get any div to move. Any help would be greatly appreciated.
Couple of problems...
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
There is no element with ID of Id0. All of your generated element IDs look like sortID...
And then...
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
inDiv.style.left has never been initiated
You're not passing inDiv through to your recursive animate call
So firstly check your element references. Then make sure you're setting the position of the div correctly, or handling scenarios where it isn't yet set. And finally make sure you pass inDiv through recursively.
Well, one more question. Since I started learning javascript short time ago, I am almost obsessed trying new things! Here it goes:
Let's say that I have an array of strings and I want to iterate on it with a navigation menu with the buttons FIRST, PREVIOUS, NEXT, LAST.
Look at this code:
var thearray = ["article1", "article2", "article3"];
var thebody = document.getElementsByTagName('body')[0];
var divcontainer = document.createElement("div");
var divpage = document.createElement("div");
function generatepage(article) {
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[article]);
paragraph.appendChild(name);
divpage.appendChild(paragraph);
}
divcontainer.appendChild(divpage);
thebody.appendChild(divcontainer);
generatepage(0); // that would be for the first article
I also figured out that generatepage(thearray.length -1)would be the call for the last article, so I have solved two buttons (before generating new content I would erase it with innerHTMLbut what I cannot think about how to do are the PREVIOUS and NEXT buttons...
Do you have any suggestion about how should I get started to make working PREVIOUS and NEXT?
I attach a JSFiddle
Thank you so much for any advice!
You can save the active page in a variable outside the function:
var page = 0;
Then you don’t need to bring any page into generatepage():
function generatepage() {
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[page]);
paragraph.appendChild(name);
divpage.appendChild(paragraph);
}
Now you can control the page from outside the function:
var next = function() {
if ( page < page.length-1 ) { page++; }
}
var prev = function() {
if ( page ) { page--; }
}
So to show the first page:
page = 0;
generatepage()
And the next:
next();
generatepage()
etc.... There are other ways too of course but this might give you an idea.
You can save a variable outside the scope of the function to memorize the current article
when you add Eventlisteners to the buttons you can call the next and previous item
but you should somehow replace the content of the div with the next one instead of appending it (i don't know a thing about manipulating dom elements)
you could try something like this:
var thearray = ["article1", "article2", "article3"];
var thebody = document.getElementsByTagName('body')[0];
var divcontainer = document.createElement("div");
var divpage = document.createElement("div");
var currentarticle
function generatepage(article) {
if(thearray[article]) {
currentarticle = article
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[article]);
paragraph.appendChild(name);
divpage.innerHTML= paragraph.innerHTML
}else {
return false
}
}
divcontainer.appendChild(divpage);
thebody.appendChild(divcontainer);
generatepage(0); // that would be for the first article
document.getElementById("next").addEventListener("click",function() {
generatepage(currentarticle + 1)
});
document.getElementById("previous").addEventListener("click",function() {
generatepage(currentarticle - 1)
});
document.getElementById("last").addEventListener("click",function() {
generatepage(thearray.length - 1)
});
document.getElementById("first").addEventListener("click",function() {
generatepage(0)
});
heres the Fiddle
I have the following function:
function slideDown() {
//get the element to slide
sliding = document.getElementById('slideDiv1');
//add 1px to the height each time
sliding.style.height = parseInt(sliding.style.height)+1+'px';
t = setTimeout(slideDown,30);
if (sliding.style.height == "401px") {
clearTimeout(t);
}
}
which is called within this function:
function addDiv(nextImageSlide) {
//finds the src attribute of the image nested in the Li
elemChild = nextImageSlide.firstChild;
imageSrc = elemChild.getAttribute('src');
//loops and creates six divs which will be the slices. adds background property etc
for (i = 0, j = 0, k = 1; i< = 19; i++, j++, k++) {
var newDiv = document.createElement('div');
newDiv.setAttribute('class', 'new-div');
newDiv.id='slideDiv' + k;
newDiv.style.height = '1px';
newDiv.style.background = 'url(' + imageSrc +') scroll no-repeat - '+39.5 * j + 'px 0';
var a = document.getElementById('content');
a.appendChild(newDiv);
}
slideDown();
}
Which is called within another function that defines nextImageSlide. It later removes all the divs that it just made.
The idea is for an image gallery. When the user hits the next button, I want slices of the next image to slide down to show the next image. Those slices are then taken away and the new image revealed.
I would like something like this: http://workshop.rs/projects/jqfancytransitions/.
It's for an assignment so we have to write all the code ourself and this is the best way I can think to replicate it. The only problem is that I keep getting an error:
'sliding is null. sliding.style.height = parseInt(sliding.style.height)+1+'px';'
No matter what I do I can't get rid of it. The thing is if I define sliding as a totally different id, (for example I made a random little div outside of everything), it working.
This error shows when I try to access the divs, it just made that it throws a hissy fit.
Anyone see any errors in my code?
Hopefully this is just a typo while pasting into the site here, but:
car a = document.getElementById('content');
^---syntax error, which'll kill your entire script - var?