Paper undefined in JS function using Raphael - javascript

Alright, so I am having a bit of trouble with Raphael and automatic updating of elements.
I've got a file called objects.js which looks something like this:
window.onload = function() {
paper = Raphael(document.getElementById('ikoner'), 600, 200);
pump = paper.circle(50,100,50);
pump.data("id","pump");
pump.data("tag",':="output".tag5:');
}
function objectFill (table) {
paper.forEach(function(e){
var tagValue = e.tag.innerHTML;
var tagId = e.id.innerHTML.trim();
if (tagValue == 0) {
paper.getById(tagId).attr({fill:"white"});
}
}
}
On my main page I've got a script which then calls objectFill on a certain interval, and updates the fill color of my objects.
Now to the problem; when I run the page I get the error that paper is undefined in objectFill. How do I make sure that objectFill will be able to find the paper? I've also tried declaring it outside like:
var paper;
window.onload = function() {
paper = Raphael(document.getElementById('ikoner'), 600, 200);
}
But I do not get that to work either. Anyone know what the problem might be?

Related

Issue with image load recursive chain on slow network/mobile

So basically I have a page with a few sections. Each sections contains 5-30 image icons that are fairly small in size but large enough that I want to manipulate the load order of them.
I'm using a library called collagePlus which allows me to give it a list of elements which it will collage into a nice image grid. The idea here is to start at the first section of images, load the images, display the grid, then move on to the next section of images all the way to the end. Once we reach the end I pass a callback which initializes a gallery library I am using called fancybox which simply makes all the images interactive when clicked(but does not modify the icons state/styles).
var fancyCollage = new function() { /* A mixed usage of fancybox.js and collagePlus.js */
var collageOpts = {
'targetHeight': 200,
'fadeSpeed': 2000,
'allowPartialLastRow': true
};
// This is just for the case that the browser window is resized
var resizeTimer = null;
$(window).bind('resize', function() {
resetCollage(); // resize all collages
});
// Here we apply the actual CollagePlus plugin
var collage = function(elems) {
if (!elems)
elems = $('.Collage');
elems.removeWhitespace().collagePlus(collageOpts);
};
var resetCollage = function(elems) {
// hide all the images until we resize them
$('.Collage .Image_Wrapper').css("opacity", 0);
// set a timer to re-apply the plugin
if (resizeTimer) clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
collage(elems);
}, 200);
};
var setFancyBox = function() {
$(".covers").fancybox({/*options*/});
};
this.init = function(opts) {
if (opts != null) {
if (opts.height) {
collageOpts.targetHeight = opts.height;
}
}
$(document).ready(function() {
// some recursive functional funk
// basically goes through each section then each image in each section and loads the image and recurses onto the next image or section
function loadImage(images, imgIndex, sections, sectIndex, callback) {
if (sectIndex == sections.length) {
return callback();
}
if (imgIndex == images.length) {
var c = sections.eq(sectIndex);
collage(c);
images = sections.eq(sectIndex + 1).find("img.preload");
return loadImage(images, 0, sections, sectIndex + 1, callback);
}
var src = images.eq(imgIndex).data("src");
var img = new Image();
img.onload = img.onerror = function() {
images[imgIndex].src = src; // once the image is loaded set the UI element's source
loadImage(images, imgIndex + 1, sections, sectIndex, callback)
};
img.src = src; // load the image in the background
}
var firstImgList = $(".Collage").eq(0).find("img.preload");
loadImage(firstImgList, 0, $(".Collage"), 0, setFancyBox);
});
}
}
From my galleries I then call the init function.
It seems like my recursive chain being triggered by img.onload or img.onerror is not working properly if the images take a while to load(on slow networks or mobile). I'm not sure what I'm missing here so if anyone can chip in that would be great!
If it isn't clear what is going wrong from the code I posted you can see a live example here: https://www.yuvalboss.com/albums/olympic-traverse-august-2017
It works quite well on my desktop, but on my Nexus 5x it does not work and seems like the finally few collage calls are not happening. I've spent too long on this now so opening this up to see if I can get some help. Thanks everyone!
Whooooo I figured it out!
Was getting this issue which I'm still unsure about what it means
[Violation] Forced reflow while executing JavaScript took 43ms
Moved this into the callback that happens only once all images are loaded
$(window).bind('resize', function() {
resetCollage(); // resize all collages
});
For some reason it was getting called early even if the browser never resized causing collage to get called when no elements existed yet.
If anyone has any informative input as to why I was getting this js violation would be great to know so I can make a better fix but for now this works :):):)

Black image bug when exporting highcharts in Firefox

I am using highcharts to display several graphs on a webpage which display fine.
I have an export function that tries to combine the charts into a pdf. I am getting the svg of the chart and converting it to a jpeg image to be included in a pdf created by jsPDF.
Here is the code I am using to generate the images:
if ($('.chart').length > 0) {
var chartSVG = $('.chart').highcharts().getSVG(),
chartImg = new Image();
chartImg.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chartSVG)));
var chartCanvas = document.createElement("canvas");
chartCanvas.width = 600;
chartCanvas.height = 400;
chartCanvas.getContext("2d").drawImage(chartImg, 0, 0, 600, 400);
var chartImgData = chartCanvas.toDataURL("image/jpeg");
}
This works perfectly in Chrome but in Firefox it just returns a black image.
Does anyone know what might be going wrong or has seen a similar issue?
Thanks for your help.
UPDATE
I've updated the code but now no image is appended to the pdf document, either in Chrome or Firefox.
if ($('.sales').length > 0) {
var chartSVG = $('.sales').highcharts().getSVG(),
chartImg = new Image();
chartImg.onload = function () {
var chartCanvas = document.createElement("canvas");
chartCanvas.width = 600;
chartCanvas.height = 400;
chartCanvas.getContext("2d").drawImage(chartImg, 0, 0, 600, 400);
var chartImgData = chartCanvas.toDataURL("image/jpeg");
}
chartImg.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chartSVG)));
}
Not sure if I have the code in the correct place.
If I log 'chartImgData' to the console, both browsers generate a dataURI, but Firefox's version differs to Chromes.
UPDATE
Fixed the issue with black images. Now i'm struggling with how to return multiple images - how to nest multiple callbacks or is there another way?
Example: jsfiddle.net/wmuk489c/2
SOLVED
Thanks for your help #RobertLangson. fiddle updated with final working code should anyone need it: http://jsfiddle.net/wmuk489c/3/
FURTHER ISSUES:
My charts are dynamic and so may not always be present. I need to get an image from each graph that exists. If the graph does not exist, the 'getSVG' function fails, see example: http://jsfiddle.net/wmuk489c/4/
How should the img.onload work if the chart doesn't exist? The first chart in the callback may not be present either, so how would this work? Is there a better way to get the images?
setting chartImg.src causes an asynchronous load so you then need to do this...
chartImg.onload = function() {
var chartCanvas = document.createElement("canvas");
chartCanvas.width = 600;
chartCanvas.height = 400;
chartCanvas.getContext("2d").drawImage(chartImg, 0, 0, 600, 400);
var chartImgData = chartCanvas.toDataURL("image/jpeg");
doc.addImage(chartImgData, 'JPEG', 0, 0, 200, 100);
// You can only do this bit after you've added the image so it needs
// to be in the callback too
doc.save('test.pdf');
}
chartImg.src = ...
You've a race condition otherwise and I imagine you just happen to get away with it with the Chrome browser on your PC.
Here's your fiddle fixed.

Javascript class on path element

I'm creating a interactive map with svg and I have converted the svg format to a javasript file (rahpael). I want to put a class on a path element, to create a hover effect, but I can't seem to get it to work:
var path_cz = rsr.path("M513.4,537l-329,19.3L209.5,666c0,0,9.5,36.8,51.5,48.8l108,22.7c13.3-16.7,119-43.4,175.6-8.7l165.7-58.6 c0,0,210.2-54.5,113.6-150.5c-33.3-27.3-61.9-50.4-61.9-50.4l-72.8-5.5l-46.9,2l-154,6.7l-2.6,21L513.4,537z").attr({fill: '#4F217C',parent: 'farver','stroke-width': '0','stroke-opacity': '1'}).data('id', 'path_cz');
I've tried .attr("class","classname"); and some other stuff inside .attr, but still nothing..
Any suggestions would be appreciated, thx :)
As you are using Raphael JS, the easiest way to do this is to hook into the hover method that Raphael supplies out of the box and update it that way.
$(document).ready(function() {
var rsr = Raphael(0, 0, 1000, 1000);
var path_cz = rsr.path("M513.4,537l-329,19.3L209.5,666c0,0,9.5,36.8,51.5,48.8l108,22.7c13.3-16.7,119-43.4,175.6-8.7l165.7-58.6 c0,0,210.2-54.5,113.6-150.5c-33.3-27.3-61.9-50.4-61.9-50.4l-72.8-5.5l-46.9,2l-154,6.7l-2.6,21L513.4,537z").attr({fill: '#4F217C',parent: 'farver','stroke-width': '0','stroke- opacity': '1'}).data('id', 'path_cz');
path_cz.hover(function() {
path_cz.node.setAttribute('class', 'one');
}, function() {
path_cz.node.setAttribute('class', 'two');
});
});
For an example, here is a fiddle: http://jsfiddle.net/n9Mt6/1/

Add transition to images on my website

I have this code:
<script type="text/javascript">
var aImages = [
"images/gaming/GTAV/GTAVReviewImage1.jpg",
"images/gaming/GTAV/GTAVReviewImage2.jpg",
"images/gaming/GTAV/GTAVReviewImage3.jpg",
"images/gaming/GTAV/GTAVReviewImage4.jpg",
"images/gaming/GTAV/GTAVReviewImage5.jpg",
"images/gaming/GTAV/GTAVReviewImage6.jpg",
"images/gaming/GTAV/GTAVReviewImage7.jpg"];
var oImage = null;
var iIdx = 0;
function play() {
try {
if (oImage===null) { oImage=window.document.getElementById("review-images"); }
oImage.src = aImages[(++iIdx)%(aImages.length)];
setTimeout('play()',5000);
} catch(oEx) {
}
}
</script>
which changes the image on this page: http://chrisbrighton.co.uk/GTAV.php every five seconds.
How can I add image transition to it?
UPDATE: When I add -webkit-transition to the img tag nothing happens.
Thanks.
There are different ways to do it. A lot of people have went to CSS3 now that there is some really cool animating and transition effects... You can control your ccs3 effects using javascript. For a detailed tutorial check - controlling animations with javascript

JavaScript waiting until an image is fully loaded before continuing script

I've been looking around a lot of JavaScript answers but I haven't found one that really answers my problem yet. What I'm trying to do is load an image, grab the pixel data, perform an analysis, and then load another image to repeat the process.
My problem is that I can't preload all of the images because this script has to be able to work on large amounts of images and preloading could be too resource heavy. So I'm stuck trying to load a new image each time through a loop, but I'm stuck with a race condition between the image loading and the script drawing it to the canvas's context. At least I'm pretty sure that's what is happening because the script will work fine with the images precached (for example if I refresh after loading the page previously).
As you'll see there are several lines of code commented out because I'm incredibly new to JavaScript and they weren't working the way I thought they would, but I didn't want to forget about them if I needed the functionality later.
This is the snippet of code that I believe is giving rise to the problem:
EDIT: So I got my function to work after following a suggestion
function myFunction(imageURLarray) {
var canvas = document.getElementById('imagecanvas');
console.log("Canvas Grabbed");
if (!canvas || !canvas.getContext) {
return;
}
var context = canvas.getContext('2d');
if (!context || !context.putImageData) {
return;
}
window.loadedImageCount = 0;
loadImages(context, canvas.width, canvas.height, imageURLarray, 0);
}
function loadImages(context, width, height, imageURLarray, currentIndex) {
if (imageURLarray.length == 0 || imageURLarray.length == currentIndex) {
return false;
}
if (typeof currentIndex == 'undefined') {
currentIndex = 0;
}
var currentimage = new Image();
currentimage.src = imageURLarray[currentIndex];
var tempindex = currentIndex;
currentimage.onload = function(e) {
// Function code here
window.loadedImageCount++;
if (loadedImageCount == imageURLarray.length) {
// Function that happens after all images are loaded here
}
}
currentIndex++;
loadImages(context, width, height, imageURLarray, currentIndex);
return;
}
Maybe this will help:
currentimage.onload = function(e){
// code, run after image load
}
If it is necessary to wait for the image to load, the following code will load the next image (currentIndex is your "img" variable):
var loadImages = function(imageURLarray, currentIndex){
if (imageURLarray.length == 0 || imageURLarray.length == currentIndex) return false;
if (typeof currentIndex == 'undefined'){
currentIndex = 0;
}
// your top code
currentimage.onload = function(e){
// code, run after image load
loadImages(imageURLArray, currentIndex++);
}
}
Instead of a "for" loop, use for example this function:
loadImages(imageURLarray);
Maybe try this:
http://jsfiddle.net/jnt9f/
Setting onload handler before setting img src will make sure the onload event be fired even the image is cached
var $imgs = $(),i=0;
for (var img = 0; img < imageURLarray.length; img++) {
$imgs = $imgs.add('<img/>');
}
var fctn = (function fctn(i){
$imgs.eq(i).on('load',function(){
//do some stuff
//...
fctn(++i);
}).attr('src',imageURLarray[i]);
})(0);
Actually...a lot of developers are pointing here to detect when images are done loading after a jQuery event..
https://github.com/desandro/imagesloaded
If you can determine when the event triggers your images to load (for example, adding an Id or class onto the page right before your images begin to load), then you should be able to blend that in with this plug-in on github.
Good Luck!

Categories

Resources