Node-Red Dashboard: Determine width and height of a group - javascript

In a NR dashboard I'm trying to determine the width and heigth of a widget group:
var groupWidth = document.getElementById('Home_Test2_cards').offsetWidth;
var groupHeight = document.getElementById('Home_Test2_cards').offsetHeight;
It works for groupWidth but not for groupHeight. I found some references that a div will not return its height when set to invisible but this is not the case here. Is there any way to determine the height?
Using jQuery:
Calling var groupHeight = $('#Home_Test2_cards').height(); works but still only returns 0.
Edit:
Browser Screenshot
Dashboard Template content:
<script>
(function(scope) {
scope.$watch('msg.payload', function(data) {
if (data !== undefined) {
imageObj.src=data;
}
});
}(scope));
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var groupWidth = document.getElementById('Home_Test2_cards').offsetWidth;
//var groupHeight = document.getElementById('Home_Test2_cards').offsetHeigth;
var groupHeight = $('#Home_Test2_cards').height();
console.log('Width:' + groupWidth);
console.log('Height:' + groupHeight);
var imageObj = new Image();
imageObj.onload= function() {
var wRatio = groupWidth / imageObj.width;
var hRatio = groupHeight / imageObj.height;
var ratio = Math.min(wRatio, hRatio);
context.drawImage(imageObj, 0, 0, canvas.width, canvas.height, 0, 0, imageObj.width*ratio, imageObj.height*ratio);
};
</script>
<canvas id="myCanvas"></canvas>
Based on the screenshot above I would expect the height to be 351.

The node-red Dashboard includes the JQuery library, so you should be able to use:
var groupWidth = $('#Home_Test2_cards').width;
var groupHeight = $('#Home_Test2_cards').height;

Related

jsPDF save to serverside

My code is working correct. It's capturing and generating the whole page and prompting download too. But I need this to be saved on my server automatically in "uploads/pdfs/" folder. I actually want to send this through php mail and save it on the server instead of prompting. Please help me.
This is my script:
function makePDF() {
var quotes = document.getElementById('container-fluid');
html2canvas(quotes, {
onrendered: function(canvas) {
//! MAKE YOUR PDF
var pdf = new jsPDF('p', 'pt', 'letter');
for (var i = 0; i <= quotes.clientHeight/980; i++) {
//! This is all just html2canvas stuff
var srcImg = canvas;
var sX = 0;
var sY = 1278*i; // start 980 pixels down for every new page
var sWidth = 990;
var sHeight = 1278;
var dX = 0;
var dY = 0;
var dWidth = 990;
var dHeight = 1278;
window.onePageCanvas = document.createElement("canvas");
onePageCanvas.setAttribute('width', 990);
onePageCanvas.setAttribute('height', 1278);
var ctx = onePageCanvas.getContext('2d');
// details on this usage of this function:
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);
// document.body.appendChild(canvas);
var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);
var width = onePageCanvas.width;
var height = onePageCanvas.clientHeight;
//! If we're on anything other than the first page,
// add another page
if (i > 0) {
pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
}
//! now we declare that we're working on that page
pdf.setPage(i+1);
//! now we add content to that page!
pdf.addImage(canvasDataURL, 'PNG', 0, 0, (width*.62), (height*.62));
}
pdf.save('output.php')
}
});
}

Why do I get "Cannot read property...of undefined with this object?

Could someone help me figure out what the problem is. I get the error "TypeError: Cannot read property 'draw_map' of undefined(…)" in browser when running the code below:
$(document).ready(function() {
Maps = function(id, img_src, width, height) {
var self = {
id: id,
img: new Image(),
width: width,
height: height
}
self.img.src = img_src;
self.draw_map = function() {
ctx.drawImage(self.img, 0, 0, self.img.width, self.img.height, 100, 100, self.img.width * 2, self.img.height * 2);
}
}
function update_canvas() {
current_map.draw_map();
}
///////////////////////////////////////////
// get context to draw on canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// Load Image for map
var current_map = Maps("field", "img/dirt.jpeg", 120, 480);
// Drawing
setInterval(update_canvas, 500);
}); // End of Document.ready
Probably because the function
Maps = function(...) { ... }
doesn't return self object.
Probably you want to use it as a construction function so change this line using new operator:
var current_map = new Maps("field", "img/dirt.jpeg", 120, 480);
Here is a working code (with the HTML elements commented out). The problem was that you are not using the this reference inside the function constructor and then not using the new operator to create an instance.
$(document).ready(function() {
Maps = function(id, img_src, width, height) {
this.id = id;
this.width = width;
this.height = height;
this.img = new Image() // replace with your Image
this.img.src = img_src;
var self = this; // Required for the draw_map function
this.draw_map = function() {
console.log("Draw image", self.img.width, self.img.height);
// Uncomment in your code: ctx.drawImage(self.img, 0, 0, self.img.width, self.img.height, 100, 100, self.img.width * 2, self.img.height * 2);
}
}
function update_canvas() {
current_map.draw_map();
}
///////////////////////////////////////////
// get context to draw on canvas. Uncomment
//var canvas = document.getElementById("canvas");
//var ctx = canvas.getContext("2d");
// Load Image for map
var current_map = new Maps("field", "img/dirt.jpeg", 120, 480);
// Drawing
setInterval(update_canvas, 500);
}); // End of Document.ready
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Prevent simultanous function calls when using pdf.js?

I use pdf.js to show pdf files, but the result is not good, please have a look at my code.
My codes are as follows.
var aaa = function (pdf, page_number) {
pdf.getPage(page_number).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = $('.pdf-view')[page_number-1];
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
};
for (var i = 1;i < 51;i++) {
aaa(pdf, i);
if (i !== 50) {
var a = '<canvas data="{{ raw_path }}" class="pdf-view hide" style="margin-bottom:10px;"></canvas>';
$('#file-view #pdf').append(a);
}
}
There is a loop, then 50 functions (aaa) execute at the same time. The effect is disastrous, and my computer gets stuck. I want to excute a function right after the last function excuted very well.
Please help me improve it. Thank a lot. (Sorry, my English is disastrous as well.)
To avoid simultaneous run of single page load and render function aaa , you should move its call to callback of the page load - .then( part so it's called recursively. And then call aaa function only once with page_number = 1.
//define page render function
var aaa = function (pdf, page_number) {
pdf.getPage(page_number).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = $('.pdf-view')[page_number-1];
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
if (i < 50) {
//render first 50 pages but not all pages except #50
aaa(pdf, i);
i++;
}
});
};
//pre-generate 50 canvases
var docFragment = document.createDocumentFragment();
for (var i = 1;i < 51;i++) {
var c = document.createElement("canvas");
$(c).data({{ raw_path }});
$(c).addClass('pdf-view hide');
$(c).css('margin-bottom', '10px');
docfrag.appendChild(c);
}
$('#file-view #pdf').append(docfrag);
//call render
var i = 1;
aaa(pdf, i);

Images not loading on website

The problem I have is that when the page is loaded sometimes it displays all the images, sometimes just 2 images and sometimes all. I don´t know why this is happening.
Any ideas?
$('#banners .box img').each(function(index){
var randval = (index+1)*100;
var _this = $(this)
setTimeout(function(){
_this.attr('id' , 'banner' + index);
to_canvas('banner' + index, 300, 223);
}, randval)
});
to_canvas function:
function to_canvas(im,w,h){
var canvas;
var imageBottom;
var im_w = w;
var im_h = h;
var imgData;
var pix;
var pixcount = 0;
var paintrow = 0;
var multiplyColor = [70, 116, 145];
var x_offset = Math.floor(($('#'+im).attr('width') - im_w)/2);
var y_offset = Math.floor(($('#'+im).attr('height') - im_h)/2);
imageBottom = document.getElementById(im);
canvas = document.createElement('canvas');
canvas.width = im_w;
canvas.height = im_h;
imageBottom.parentNode.insertBefore(canvas, imageBottom);
ctx = canvas.getContext('2d');
ctx.drawImage(imageBottom, -x_offset , -y_offset);
imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pix = imgData.data;
for (var i = 0 ; i < pix.length; i += 4) {
if(pixcount > im_w - (im_h - paintrow) ){
pix[i ] = multiply(multiplyColor[0], pix[i ]);
pix[i+1] = multiply(multiplyColor[1], pix[i+1]);
pix[i+2] = multiply(multiplyColor[2], pix[i+2]);
}
if(pixcount < im_w-1){
pixcount++;
}else{
paintrow++;
pixcount = 0;
}
}
ctx.putImageData(imgData, 0, 0);
$('#'+im).remove();
}
function multiply(topValue, bottomValue){
return topValue * bottomValue / 255;
}
I'm using the canvas function to add a triangle with multiply effect (like Photoshop).
Make sure the images are loaded :
$('#banners .box img').each(function(index, elem){
var randval = (index+1)*100,
self = this,
img = new Image(); // create image object
img.onload = function() { // wait until it's loaded
setTimeout(function(){
self.id = 'banner' + index;
to_canvas('banner' + index, 300, 223);
}, randval)
}
img.src = elem.src; // set source to same as elem
});
Wrap it all in this code to make sure the images are loaded before you execute your script. When you initially load your page, it caches the images(stores them in temp memory), but not before all your elements are rendered. When you reload, it reads the images from the cache–which is much faster than refetching the images again from the server–and therefore the images load about the same time everything else does. This results in visible images.
Like I said, to get your page to work, make sure everything is loaded, then run your script.
$(window).load(function(){
...your scripts(you can exclude functions definitions from this scope)
}

wrong image height in canvas

I have a canvas like this
<canvas id="canvas" width="600px" height="300px"></canvas>
Now I am trying to show image inside the canvas of some 260px width and height. But its showing the image full screened in canvas. What I am doing wrong?
img.onload = function(){
var im = this;
var imgWidth = im.width;
var imgHeight = im.height;
var imgScaledWidth = 0;
var imgScaledHeight = 0;
imgScaledHeight = self.conHeight - 40;
imgScaledWidth = imgScaledHeight * (imgWidth/imgHeight);
self.context.drawImage(this, 0,0,imgScaledWidth,imgScaledHeight);
}
Its showing like this
There's no reason why your code shouldn't be working based on what you've shown in the question. Here is an example based on the code you've given with some minor changes to account for not having a self variable.
<script>
var img = document.getElementById("image");
var c = document.getElementById("canvas");
var con = c.getContext("2d");
img.onload = function(){
var im = this;
var imgWidth = im.width;
var imgHeight = im.height;
var imgScaledWidth = 0;
var imgScaledHeight = 0;
var off=20;
imgScaledHeight = c.height - off;
imgScaledWidth = imgScaledHeight * (imgWidth/imgHeight);
con.drawImage(this, 0,0+(off/2),imgScaledWidth,imgScaledHeight);
}
</script>
You are stretching it. If you don't want to show the image stretched, just don't pass any size to drawImage:
self.context.drawImage(this, 0, 0);

Categories