Paper.js - compatibilty with Chrome and IE - cross-browser

I'm trying to do a silly thing : a flying sausage on a HTML page.
I'm trying to do it from Paper.js
http://paperjs.org/
here is the HTML code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>SkyWurst</title>
<!-- Load the Paper.js library -->
<script type="text/javascript" src="paper.js">
</script>
<!--Load external PaperScript and associate it with myCanvas -->
<script type="text/paperscript" src="saucisse.js" canvas="myCanvas">
</script>
</head>
<body>
<canvas id="myCanvas" width="1600" height="900"
id="tools_sketch" width="1600" height="900"
style="background: url(sky.jpg) no-repeat center center;">
</canvas>
</body>
</html>
and here is the saucisse.js
// Adapted from the following Processing example:
// http://processing.org/learning/topics/follow3.html
// The amount of points in the path:
var points = 10;
// The distance between the points:
var length = 25;
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 70,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++)
path.add(start + new Point(i * length, 0));
function onMouseMove(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
var vector = segment.point - nextSegment.point;
vector.length = length;
nextSegment.point = segment.point - vector;
}
path.smooth();
}
function onMouseDown(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
function onMouseUp(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
sky.jpg, paper.js, saucisse.js and saucisse.html are in the same folder
Everything is fine with Firefox but with Chrome and IE, there is only the sky, and no sausage. Very sad.
Any idea ?

I can't say definitively but I suspect that either paper.js or saucisse.js is not loading when you run it locally. It could be because the files are missing or in the wrong place.
Another possibility is that the server paper.js is paper-full.js while the local paper is paper-core.js. If that's the case both files would load but the saucisse script would fail because the paperscript features aren't loaded.
I did embed saucisse.js within the HTML file and referenced a version of paper that I know was correct and that runs locally using Chrome, IE, and Firefox. I don't know why Firefox runs correctly. Maybe Firefox had a tab that was already open to a correctly working version before you made a change that broke things? If so, it will continue to work until you reload the page.

Related

Google Docs Viewer occasionally failing to load content in iframe

I'm having an issue with the Google Docs viewer that is causing a nightmare to solve because it only happens intermittently. I'm looking for guidance on how to make the content in the iframe load everytime without issue as it should.
Steps to reproduce
1) This page is a basic HTML page with a h1 tag and an iframe containing a link to a PDF on the same server
http://bit.ly/1mqbuf7
2) When you load the page, the pdf document will load in the iframe 60% of the time.
3) If you hit refresh 10 or so times, at least once it will fail to appear. Google returns a 307 first (Which it also does when it works) and then returns a 204 - no content. When it works, it returns a 200, with the content you see in the viewer.
I'm struggling to understand why it only does this some of the time with no visible errors. This has been tested and failed on Google Chrome v 48.0.2564.103 (PC) and Internet Explorer Edge v25.10586 (PC) with the same results and frequency of failure.
Any guidance would be greatly appreciated.
This is not fixing your problem per se, but since I had the same problem and I eventually managed to find an acceptable solution, I thought I'd share it.
var $docViewer = $(`<iframe src="${newValue}" height="100%" width="100%"></iframe>`);
//If using modern browser, use and embed object
if (window.chrome || typeof (window.mozInnerScreenX) != "undefined")
$docViewer = $(`<object width="100%" height="100%" data="${newValue}" type="application/pdf">
<embed src="${newValue}" type="application/pdf">
<p>This browser does not support PDFs.Please download the PDF to view it: Download PDF.</p>
</embed>
</object>`);
//Add the new viewer
$docViewer.appendTo($("#invoicePreview"));
Basically, use an embed if modern browser, and the gviewer if not. The embed object behaves identically to the google doc viewer, it works in 100% of cases (no failed loads), but since it's not supported for IE and/or low-end mobile devices, use the google doc viewer for that... Progressive Enhancements I guess.
Here's a "hack" that will ensure a proper loading every time (albeit with some delay, due to potential failed attempts - it's Google's fault, don't shoot the messenger!). The 2s interval duration can be modified to best fit the time expected for a successful effort to start loading the iFrame.
HTML:
<div id="test-id-1" style="text-align: center; width: 100%; height: 1150px" class="embed-pdf" data-url="{insert_pdf_link_here}"><span class="loader">Please wait...</span></div>
JS:
$(document).ready(function() {
let embed_pdfs = {};
$('.embed-pdf').each(function() {
var $pdfViewer = $('<iframe src="https://docs.google.com/viewer?url=' + $(this).data('url') + '&embedded=true" style="width: 100%; height: 100%" frameborder="0" scrolling="no"></iframe>');
$pdfViewer.appendTo($(this));
console.log($(this).attr('id') + " created");
embed_pdfs[$(this).attr('id')] = 'created';
});
$(document).find('.embed-pdf iframe').load(function(){
embed_pdfs[$(this).parents('.embed-pdf').attr('id')] = 'loaded';
$(this).siblings('.loader').remove();
console.log($(this).parents('.embed-pdf').attr('id') + " loaded");
});
let embed_pdf_check = setInterval(function() {
let remaining_embeds = 0;
$.each(embed_pdfs, function(key, value) {
try {
if ($($('#' + key)).find('iframe').contents().find("body").contents().length == 0) {
remaining_embeds++;
console.log(key + " resetting");
$($('#' + key)).find('iframe').attr('src', src='https://docs.google.com/viewer?url=' + $('#' + key).data('url') + '&embedded=true');
}
}
catch(err) {
console.log(key + " reloading");
}
});
if (!remaining_embeds) {
clearInterval(embed_pdf_check);
}
}, 2000);
});
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="iframeContainer"></div>
</body>
<script>
var URL = "https://docs.google.com/viewer?url=http://www.africau.edu/images/default/sample.pdf&embedded=true";
var count = 0;
var iframe = ` <iframe id = "myIframe" src = "${URL}" style = "width:100%; height:500px;" frameborder = "0"></iframe>`;
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function(){
count++;
if(count>0){
clearInterval(ref)
}
});
var ref = setInterval(()=>{
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function() {
count++;
if (count > 0) {
clearInterval(ref)
}
});
}, 4000)
</script>
</html>
Change var URL = your_googel_docs_pdf_url
The code will keep loading the url into iframe until the doc loads successfully.
It's not the best solution. But I waited a few seconds after the page loaded and checked if the iframe was loaded (see how below). If it wasn't, then I set the iframe's src attribute to null and then back to the correct source, affectively reloading it. Then waited a few seconds to check again and repeated. Once it has loaded you can stop checking.
conditionalPdfIFrameReloadTimeout() {
setTimeout(() => {
let iFrame = document.GetElementById("pdfIframe")
if (iFrame.contentDocument/*pdf iframe failed to load*/) {
iFrame.src = null
iFrame.src = "the url to your pdf"
conditionalPdfIFrameReloadTimeout()
}
}, 6000)
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" style="width:100%; height:100%;">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body id="iframeContainer" style="height: 100%; width: 100%; overflow: hidden; margin:0px;">
<script>
var URL = "https://docs.google.com/gview?url=enteryoururl&embedded=true";
var count = 0;
var iframe = `<iframe id = "myIframe" src = "${URL}" style="width:100%; height:100%;" frameborder="0" allowfullscreen=""></iframe>`;
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function(){
count++;
if(count>0){
clearInterval(ref)
}
});
var ref = setInterval(()=>{
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function() {
count++;
if (count > 0) {
clearInterval(ref)
}
});
}, 2000)
</script>
</body>
</html>
The above code worked for me.

Overcoming connection limitation with mobile safari

I recently discovered that mobile safari (on iOS 9.1 - though unsure about older safari versions) has an unfortunate problem with multiple connections and images. If you have six images when you load a page, it will delay XHR requests that loads after those six images by a huge lag time (order of 30s).
For example, I loaded the following using a standard NodeJS/Express server and saw giant delays before the alert showed up - despite the fact that all there images are just a couple of KB and I can visibly see that they are all loaded. The dev console also shows the images loaded but not the XHR request. The duration it took to download the file was very small but the latency was huge.
This is not a problem on any other browsers (mobile chrome, regular safari, etc).
Sample problem html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="/static/images/home/payment.png">
<img src="/static/images/home/couple-present-mobile.jpg">
<img src="/static/images/general/welcome.jpg">
<img src="/static/images/general/arrow-down.png">
<img src="/static/images/general/arrow-right.png">
<img src="/static/images/general/check.png">
<script>
var url = '/static/test.html'
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
alert(url) //This takes forever
};
xhr.send();
</script>
</body>
</html>
An odd thing is if you ran the XHR request BEFORE there were 6 images, it would work perfectly. In fact, if you even did something like this one below, it was fine. I think this works because the background CSS image must retrieve the URL after the XHR is initiated.
Replace one of the img tags with a background css image and it works:
<!DOCTYPE html>
<html>
<head>
<style>
.test {
background-image: url("/static/images/home/check.png");
height: 400px;
}
</style>
</head>
<body>
<img src="/static/images/home/payment.png">
<img src="/static/images/home/couple-present-mobile.jpg">
<img src="/static/images/general/welcome.jpg">
<img src="/static/images/general/arrow-down.png">
<img src="/static/images/general/arrow-right.png">
<!--<img src="/static/images/general/check.png"> REMOVE THIS LINE and add the background image instead-->
<div class="test"></div>
<script>
var url = '/static/test.html;
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
console.log(url) //NO DELAYS!
};
xhr.send();
</script>
</body>
</html>
Also I found out that just running 7 simultaneous XHR requests also does not cause this problem (such as the below):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
var urls = ['/static/images/home/payment.png',
'/static/images/home/couple-present-mobile.jpg',
'/static/images/general/arrow-right.png',
'/static/images/general/arrow-down.png',
'/static/images/general/welcome.jpg',
'/static/images/general/check.png',
'/static/test.html'];
for(var i = 0, ii = urls.length; i < ii; i++){
(function(){
var url = urls[i];
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
console.log(url)
};
xhr.send();
})()
}
</script>
</body>
</html>
Has anyone come across this problem and figured out a way to deal with it without reducing the number of images or putting them in a sprite or something?
The hack I ultimately used to get around this was to load the images from a different host. For simplicity, if the browser detected that the host was www.domain.com, I would load images it from domain.com and vice versa. You can also just have all your images come from a certain host like images.domain.com and keep your api's and other stuff on another host.
Not the most ideal or elegant solution, but its super simple to implement and solves the problem.

Uncaught ReferenceError: Stage is not defined using EaselJS

I'm setting up a quick little test to start digging into EaselJS but I'm getting this error, Uncaught ReferenceError: Stage is not defined. I'm unsure as to why Stage is not defined as I checked easeljs-NEXT.combined.js for the Stage method and it's definitely in there. What am I doing wrong here?
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Easel Intro</title>
<!-- EaselJS Library -->
<script src="js/vendor/easeljs-NEXT.combined.js"></script>
<script>
var stage;
var text;
var logo;
function init()
{
stage = new Stage(document.getElementById("canvas"));
logo = new Bitmap("img/HTML5_Logo_64.png");
logo.regX = logo.image.width * 0.5;
logo.regY = logo.image.height * 0.5;
stage.addChild(logo);
text = new Text("Text rendered on the canvas.", "36px Arial", "#666");
text.x = 100;
text.y = 100;
stage.addChild(text);
stage.update();
}
</script>
</head>
<body onload="init();">
<canvas id="canvas" width="960" height="580"></canvas>
</body>
</html>
You need to prefix all CreateJS classes with createjs..
new createjs.Stage("canvas");
This goes for all items in your example: Stage, Bitmap, and Text.
There may be out-of-date documentation or examples out there, since early versions (2011 or so) didn't have a namespace.

Working with HTML5 Canvas

I am working with some image manipulations and I am trying to have a basic canvas and I have a text box now If I enter any text it should change immediately on the canvas and I need that text to move on the canvas and record it's X and Y positions.So how do I do that?
Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
var drawLogo = function () {
var canvas = document.getElementById('my_canvas');
var context = canvas.getContext('2d');
context.font = 'italic 40px sans-serif';
context.textBaseline = 'top';
context.fillText('Some text', 60, 0);
};
$(function () {
var canvas = document.getElementById('my_canvas');
if (canvas.getContext) {
drawLogo();
}
});
</script>
</head>
<body>
<canvas id="my_canvas" width="900" height="300">
Fallback content here
</canvas>
<input id="Text1" type="text" />
</body>
</html>
First, everytime the text changes you'll need to re-draw the ENTIRE canvas.
Do this:
Add a myText, x & y inputs to your drawLogo function: drawLogo(myText, x, y) and change this line to context.fillText(myText, x, y);
To change text on the canvas, add a JS event handler to the textbox and call the new drawLogo function passing all 3 input parameters.
Keep in mind that you cannot modify what's drawn on a Canvas. You can only draw it once so all modifiers have to be done in one pass.
The moving part is not clear but you'll need to calculate your equations of motion in JS beforehand. When you call the new drawLogo(myText, x, y) you'll pass these values from JS.
Watch out for this line context.textBaseline = 'top'; as last time I checked it wasn't supported in Firefox.

HTML5 Video to Canvas. Cant save the image

The problem I am having is the following:
I use a video and a canvas tag and capture a frame from the video tag and place it into the canvas tag, but when I create a reference of the canvas in javascript so that I may return the dataURL it bombs out. Please note the video is local, is this setting the canvas origin-clean flag to false even though it is local? I have tested in Firfox 3.6, IE9 Beta, Safari 5.0.3 and it fails on each of them.
Here is the code I use to place the frame from the video:
var video = document.getElementById(“video”);
var canvasDraw = document.getElementById(‘imageView’);
var w = canvasDraw.width;
var h = canvasDraw.height;
var ctxDraw = canvasDraw.getContext(’2d’);
ctxDraw.clearRect(0, 0, w, h);
ctxDraw.clearRect(0, 0, w, h);
ctxDraw.drawImage(video, 0, 0, w, h);
The above works perfectly.
Below is the code to get the dataURL:
function getURIformcanvas() {
var ImageURItoShow = “”;
var canvasFromVideo = document.getElementById(“imageView”);
if (canvasFromVideo.getContext) {
var ctx = canvasFromVideo.getContext(“2d”); // Get the context for the canvas.
var ImageURItoShow = canvasFromVideo.toDataURL(“image/png”); //<– It fails on this line.
}
var doc = document.getElementById("txtUriShow");
doc.value = ImageURItoShow;
}
It always fails on the line:
var ImageURItoShow = canvasFromVideo.toDataURL("image/png");
Any thought on what might be the problem. If I load a normal image into the canvas it works fine, but as soon as I load the image from video into the canvas that line fails.
Any ideas?
Here is the complete page code, to reproduce the error follow the following steps:
Click the "Capture" button. (an image will be captured from the video, very important to do this first!!)
Click the "View URI" button. (this is supposed to create the toDataURL of the video image in the canvas and place it in the textbox, but it does not work)
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Video.aspx.vb" Inherits="Video" %>
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta content="" charset="utf-8" />
<title>Video to Canvas</title>
</head>
<body>
<script type="text/javascript">
</script>
<table>
<tr>
<td>
<p style="height:21px"></p>
<video id="video" width="400px" height="300px" controls="true">
<source src="gizmo.mp4">
<source src="gizmo.ogv">
<source src="gizmo.webm">
</video><br/>
<button onclick="capture()" style="width: 64px;border: solid
2px #ccc;">Capture</button><br/>
</td>
<td style="vertical-align:top">
<button onclick="getURIformcanvas()" style="width: 64px;border: solid
2px #ccc;">View URI</button></p>
<div id="container" style="border:none">
<canvas id="imageView" style="position: absolute; left: 0; top: 0;
z-index: 0;border:none" width="400" height="300">
<p>Unfortunately, your browser is currently unsupported by our web
application. We are sorry for the inconvenience. Please use one of
the
supported browsers listed below, or draw the image you want using an
offline tool.</p>
<p>Supported browsers: Opera, Firefox, Safari, and Konqueror.</p>
</canvas>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<input type="text" id="txtUriShow" name="txtUriShow" value="" />
<img type="text" id="img1" name="img1" value="" />
</td>
</tr>
</table>
<script>
function getURIformcanvas() {
var ImageURItoShow = "";
var canvasFromVideo = document.getElementById("imageView");
if (canvasFromVideo.getContext) {
var ctx = canvasFromVideo.getContext("2d"); // Get the context for the canvas.canvasFromVideo.
var ImageURItoShow = canvasFromVideo.toDataURL("image/png");
}
var doc = document.getElementById("txtUriShow");
doc.value = ImageURItoShow;
}
var videoId = 'video';
function capture() {
var video = document.getElementById("video");
var canvasDraw = document.getElementById('imageView');
var w = canvasDraw.width;
var h = canvasDraw.height;
var ctxDraw = canvasDraw.getContext('2d');
ctxDraw.clearRect(0, 0, w, h);
ctxDraw.drawImage(video, 0, 0, w, h);
ctxDraw.save();
}
</script>
</body>
</html>
These files are local in you HDD, or by local you mean that the video is in the same folder as the html/js files?
You have to put all the files somewhere in the web to test it appropriately.