html5 canvas element disappears - javascript

I have a <canvas> element that I put in a div using jQuery. The lines I draw on that canvas appear and then disappear very quickly.
When I put text inside the $('#solutionDiv') div, it appears when the page loads, and then gets covered (briefly) by my canvas, and then reappears when the canvas vanishes. This happens in FireFox and Chrome. I am using a library for sliders called tigra_slider_control. I don't think that's the issue, but it might be.
var solnCanvas=document.createElement('canvas'); // should be accessible through $('#solutionDiv > canvas')
solnCanvas.width = 480;
solnCanvas.height = 480;
var solnContext=solnCanvas.getContext('2d');
solnContext.strokeStyle = '#00f'; // blue lines
solnContext.lineWidth = 4;
solnContext.moveTo(50,16);
solnContext.lineTo(50,5);
solnContext.lineTo(5,5);
solnContext.stroke();
$('#solutionDiv').append(solnCanvas);
The corresponding div is:
<div id="solutionDiv" style="width:580px;height:500px;" class="boxy">
Now you see it ... <br />
Now you don't
</div>
I don't need (or want) text in this div. This is just for experimenting ... Any help would be much appreciated.

So, here is my long-awaited answer to my own question. It seems to have had something to do with the fact that I was dynamically adding the div and the canvas. When I added the div and the canvas in the html at the very outset, the canvas stayed put. This is not exactly a solution -- more of a workaround. Rather than adding the canvas later on, I just made it visible.

If you don't need (or want) the text in the div, take the text out of the div.

Related

Event listener does not work when image element blocks it [duplicate]

I have a div that has background:transparent, along with border. Underneath this div, I have more elements.
Currently, I'm able to click the underlying elements when I click outside of the overlay div. However, I'm unable to click the underlying elements when clicking directly on the overlay div.
I want to be able to click through this div so that I can click on the underlying elements.
Yes, you CAN do this.
Using pointer-events: none along with CSS conditional statements for IE11 (does not work in IE10 or below), you can get a cross browser compatible solution for this problem.
Using AlphaImageLoader, you can even put transparent .PNG/.GIFs in the overlay div and have clicks flow through to elements underneath.
CSS:
pointer-events: none;
background: url('your_transparent.png');
IE11 conditional:
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='your_transparent.png', sizingMethod='scale');
background: none !important;
Here is a basic example page with all the code.
Yes, you CAN force overlapping layers to pass through (ignore) click events.
PLUS you CAN have specific children excluded from this behavior...
You can do this, using pointer-events
pointer-events influences the reaction to click-, tap-, scroll- und hover events.
In a layer that should ignore / pass-through mentioned events you set
pointer-events: none;
Children of that unresponsive layer that need to react mouse / tap events again need:
pointer-events: auto;
That second part is very helpful if you work with multiple overlapping div layers (probably some parents being transparent), where you need to be able to click on child elements and only that child elements.
Example usage:
.parent {
pointer-events:none;
}
.child {
pointer-events:auto;
}
<div class="parent">
I'm unresponsive
I'm clickable again, wohoo !
</div>
Allowing the user to click through a div to the underlying element depends on the browser. All modern browsers, including Firefox, Chrome, Safari, and Opera, understand pointer-events:none.
For IE, it depends on the background. If the background is transparent, clickthrough works without you needing to do anything. On the other hand, for something like background:white; opacity:0; filter:Alpha(opacity=0);, IE needs manual event forwarding.
See a JSFiddle test and CanIUse pointer events.
I'm adding this answer because I didn’t see it here in full. I was able to do this using elementFromPoint. So basically:
attach a click to the div you want to be clicked through
hide it
determine what element the pointer is on
fire the click on the element there.
var range-selector= $("")
.css("position", "absolute").addClass("range-selector")
.appendTo("")
.click(function(e) {
_range-selector.hide();
$(document.elementFromPoint(e.clientX,e.clientY)).trigger("click");
});
In my case the overlaying div is absolutely positioned—I am not sure if this makes a difference. This works on IE8/9, Safari Chrome and Firefox at least.
Hide overlaying the element
Determine cursor coordinates
Get element on those coordinates
Trigger click on element
Show overlaying element again
$('#elementontop').click(e => {
$('#elementontop').hide();
$(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
$('#elementontop').show();
});
I needed to do this and decided to take this route:
$('.overlay').click(function(e){
var left = $(window).scrollLeft();
var top = $(window).scrollTop();
//hide the overlay for now so the document can find the underlying elements
$(this).css('display','none');
//use the current scroll position to deduct from the click position
$(document.elementFromPoint(e.pageX-left, e.pageY-top)).click();
//show the overlay again
$(this).css('display','block');
});
I currently work with canvas speech balloons. But because the balloon with the pointer is wrapped in a div, some links under it aren't click able anymore. I cant use extjs in this case.
See basic example for my speech balloon tutorial requires HTML5
So I decided to collect all link coordinates from inside the balloons in an array.
var clickarray=[];
function getcoo(thatdiv){
thatdiv.find(".link").each(function(){
var offset=$(this).offset();
clickarray.unshift([(offset.left),
(offset.top),
(offset.left+$(this).width()),
(offset.top+$(this).height()),
($(this).attr('name')),
1]);
});
}
I call this function on each (new) balloon. It grabs the coordinates of the left/top and right/down corners of a link.class - additionally the name attribute for what to do if someone clicks in that coordinates and I loved to set a 1 which means that it wasn't clicked jet. And unshift this array to the clickarray. You could use push too.
To work with that array:
$("body").click(function(event){
event.preventDefault();//if it is a a-tag
var x=event.pageX;
var y=event.pageY;
var job="";
for(var i in clickarray){
if(x>=clickarray[i][0] && x<=clickarray[i][2] && y>=clickarray[i][1] && y<=clickarray[i][3] && clickarray[i][5]==1){
job=clickarray[i][4];
clickarray[i][5]=0;//set to allready clicked
break;
}
}
if(job.length>0){
// --do some thing with the job --
}
});
This function proofs the coordinates of a body click event or whether it was already clicked and returns the name attribute. I think it is not necessary to go deeper, but you see it is not that complicate.
Hope in was enlish...
Another idea to try (situationally) would be to:
Put the content you want in a div;
Put the non-clicking overlay over the entire page with a z-index higher,
make another cropped copy of the original div
overlay and abs position the copy div in the same place as the original content you want to be clickable with an even higher z-index?
Any thoughts?
I think the event.stopPropagation(); should be mentioned here as well. Add this to the Click function of your button.
Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
Just wrap a tag around all the HTML extract, for example
<a href="/categories/1">
<img alt="test1" class="img-responsive" src="/assets/photo.jpg" />
<div class="caption bg-orange">
<h2>
test1
</h2>
</div>
</a>
in my example my caption class has hover effects, that with pointer-events:none; you just will lose
wrapping the content will keep your hover effects and you can click in all the picture, div included, regards!
An easier way would be to inline the transparent background image using Data URIs as follows:
.click-through {
pointer-events: none;
background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
}
I think that you can consider changing your markup. If I am not wrong, you'd like to put an invisible layer above the document and your invisible markup may be preceding your document image (is this correct?).
Instead, I propose that you put the invisible right after the document image but changing the position to absolute.
Notice that you need a parent element to have position: relative and then you will be able to use this idea. Otherwise your absolute layer will be placed just in the top left corner.
An absolute position element is positioned relative to the first parent
element that has a position other than static.
If no such element is found, the containing block is html
Hope this helps. See here for more information about CSS positioning.
You can place an AP overlay like...
#overlay {
position: absolute;
top: -79px;
left: -60px;
height: 80px;
width: 380px;
z-index: 2;
background: url(fake.gif);
}
<div id="overlay"></div>
just put it over where you dont want ie cliked. Works in all.
This is not a precise answer for the question but may help in finding a workaround for it.
I had an image I was hiding on page load and displaying when waiting on an AJAX call then hiding again however...
I found the only way to display my image when loading the page then make it disappear and be able to click things where the image was located before hiding it was to put the image into a DIV, make the size of the DIV 10x10 pixels or small enough to prevent it causing an issue then hiding the containing div. This allowed the image to overflow the div while visible and when the div was hidden, only the divs area was affected by inability to click objects beneath and not the whole size of the image the DIV contained and was displaying.
I tried all the methods to hide the image including CSS display=none/block, opacity=0, hiding the image with hidden=true. All of them resulted in my image being hidden but the area where it was displayed to act like there was a cover over the stuff underneath so clicks and so on wouldn't act on the underlying objects. Once the image was inside a tiny DIV and I hid the tiny DIV, the entire area occupied by the image was clear and only the tiny area under the DIV I hid was affected but as I made it small enough (10x10 pixels), the issue was fixed (sort of).
I found this to be a dirty workaround for what should be a simple issue but I was not able to find any way to hide the object in its native format without a container. My object was in the form of etc. If anyone has a better way, please let me know.
I couldn't always use pointer-events: none in my scenario, because I wanted both the overlay and the underlying element(s) to be clickable / selectable.
The DOM structure looked like this:
<div id="outerElement">
<div id="canvas-wrapper">
<canvas id="overlay"></canvas>
</div>
<!-- Omitted: element(s) behind canvas that should still be selectable -->
</div>
(The outerElement, canvas-wrapper and canvas elements have the same size.)
To make the elements behind the canvas act normally (e.g. selectable, editable), I used the following code:
canvasWrapper.style.pointerEvents = 'none';
outerElement.addEventListener('mousedown', event => {
const clickedOnElementInCanvas = yourCheck // TODO: check if the event *would* click a canvas element.
if (!clickedOnElementInCanvas) {
// if necessary, add logic to deselect your canvas elements ...
wrapper.style.pointerEvents = 'none';
return true;
}
// Check if we emitted the event ourselves (avoid endless loop)
if (event.isTrusted) {
// Manually forward element to the canvas
const mouseEvent = new MouseEvent(event.type, event);
canvas.dispatchEvent(mouseEvent);
mouseEvent.stopPropagation();
}
return true;
});
Some canvas objects also came with input fields, so I had to allow keyboard events, too.
To do this, I had to update the pointerEvents property based on whether a canvas input field was currently focused or not:
onCanvasModified(canvas, () => {
const inputFieldInCanvasActive = // TODO: Check if an input field of the canvas is active.
wrapper.style.pointerEvents = inputFieldInCanvasActive ? 'auto' : 'none';
});
it doesn't work that way. the work around is to manually check the coordinates of the mouse click against the area occupied by each element.
area occupied by an element can found found by 1. getting the location of the element with respect to the top left of the page, and 2. the width and the height. a library like jQuery makes this pretty simple, although it can be done in plain js. adding an event handler for mousemove on the document object will provide continuous updates of the mouse position from the top and left of the page. deciding if the mouse is over any given object consists of checking if the mouse position is between the left, right, top and bottom edges of an element.
Nope, you can't click ‘through’ an element. You can get the co-ordinates of the click and try to work out what element was underneath the clicked element, but this is really tedious for browsers that don't have document.elementFromPoint. Then you still have to emulate the default action of clicking, which isn't necessarily trivial depending on what elements you have under there.
Since you've got a fully-transparent window area, you'll probably be better off implementing it as separate border elements around the outside, leaving the centre area free of obstruction so you can really just click straight through.

HTML: Turn off Drag and Drop Shadow/Ghost

I would like to turn of the dragging-shadow that html's drag and drop shows by default. I saw this: http://www.kryogenix.org/code/browser/custom-drag-image.html for changing the image, but not completely removing the image.
When i used this:
var dragIcon = document.createElement('img');
dragIcon.src = '';
dragIcon.width = 100;
dragIcon.style.display = 'none';
event.originalEvent.dataTransfer.setDragImage(dragIcon, -100, -100);
the ghost did dissapear, but i was no longer able to drag the image. This could have to do with me having to use angularJS as well...but there is no way around that anymore at this point.
Problem:
Move a div on a page that resizes ONLY the div right above itself dynamically (inside dragging function).
Question:
I wanted to know if there is a way to turn off only the ghost, but keep all the rest of the functionality as is? This is most cosmetic than anything, but the ghost really does not add anything for me, since i am resizing everything on the fly.
Any help would be appreciated.

Canvas takes the whole document body in html and make it hidden but drawable

I found this in a stackoverflow question on how to draw in canvas http://jsfiddle.net/ArtBIT/kneDX/ and now I want the canvas to cover my whole html page. For example:
<body>
<div id="2">
//code
</div>
<div id="2">
//code
</div>
</body>
So the canvas will be attached to the page and the user could draw over the content of the page. So is there any way to create the canvas inorder to take the 100% of the body be hidden apart from the drawing lines?
Edited:
How can I draw lines continuously without making circles in the above code? Also is there any way to draw something over the text without selecting it when you pass the mouse over it?
First, make the height and width properties of the canvas equal to the page height and page width. (Getting those values is quite difficult, so see the linked questions for the best way to do it -- or just use jQuery.)
Next, add some CSS to make the canvas sit in the absolute top-left corner of the page:
#canvas {
position: absolute;
top: 0;
left: 0;
}
Then, don't change the background color of the canvas as you currently do by calling ctx.clearTo. Canvases are transparent by default, so you'll be able to see the page underneath of it, as long as you don't change the background color.
Pass in the right width and height params instead of (200, 200)
Using window.screen.width and window.screen.height gives you this: http://jsfiddle.net/kneDX/878/
Update:
With this we will end up in canvas being as big as window and not the same size as client area. See apsillers's answer.

Popup image does not stay in same place

The pop up image for "ice white" and "violet" pop up in different places. How do I make them both pop up in just one position?
Could you perhaps define a single div that uses absolute position and then on hover over Violet or Ice White, draw the popup image inside that div you created?
So something like:
var displayDiv = document.getElementById("displayDivID");
// draw popup image in the div
displayDiv.innerHTML = "<div id=\"violet\">...</div>";
displayDiv.style.display = "block"; // to show it
That way, whenever you need to display an image in the same position, it's always drawn inside that div you specified.
I would assume you have a class that controls the formatting of that div like position and borders etc.
EDIT
I've taken your code from your site and added some more code.
Save this code as a html page onto your computer and try it.
Look for the last css code snippet right before the closing tag. That block of css there controls the look of the div and position it in the middle of the page. The css only sets a fixed position. You could alternatively, use javascript to dynamically calculate the width and height of the user's browser window, then render the css code accordingly so the div is always in the middle of the browser regardless of the inner image dimension.
In your previous javascript code snippet for the displayDiv, I've fixed up a few things and added two functions for when the mouse is over a thumbnail and when it's out of a thumbnail. On mouse over will pass the url of the image to the function that will be used to render an image into the displayDiv.
Hope that helps.
EDIT 2 - Fade In and Out
You certainly can.
All you need to do is change the two functions to use jQuery fadeIn() and fadeOut() like so:
function changeDisplay(bgImageURL)
{
var displayDiv = document.getElementById("displayDiv");
// draw popup image in the div
displayDiv.innerHTML =
'<a class="popup1" href="#v"><img src="' + bgImageURL+ '" alt="" /></a>';
// show the display in case it was hidden before
$('#displayDiv').fadeIn();
}
function hideDisplay()
{
// hide it when the mouse rolls off the thumbnail
$('#displayDiv').fadeOut();
}
This jQuery is a basic one. It will have a problem where if you move your mouse on and off the thumbnail quickly, it causes the display div to come on and off, on and off, on and off even if your mouse is already off the thumbnail.
The proper way would be to rework the code and use mouseEnter and mouseLeave on the thubmnail elements.

Resizing a div to fill the browser

I have a page with many divs and style, with my div buried somewhere inside.
I am trying to have a button that automatically makes my div, that includes a video player, resize and capture the whole browser.
In order to do that I am trying to get the current position of the div and then position it relatively so that it'll get to the top-left corner so I could then use document.body.clientHeight/clientWidth.
Can't get this to work.
I tried the approach of moving my div to the first div and then resizing however this messes up the flash player.
Any ideas? any different approaches?
Thanks,
Guy
Use one of the lightbox clones that can handle DIVs. They usually copy the DIV in question into their own view DIV, which helps with positioning issues and you don't have to do anything to the buried div.
I find Multi-Faceted lightbox to be very easy for customizations:
http://www.gregphoto.net/lightbox/
but there are lots of others around as well.
Why relative?
You should rather use fixed instead of relative. Then set positon to 0,0 and width and height to 100%.
Simple js can do this.
On click, just set the div's style to 'fixed', and position 0,0. Like:
var theDiv = document.getElementById('yourDivsId');
theDiv.style.position = 'fixed';
theDiv.style.top = 0;
theDiv.style.left = 0;
This should do the trick:
<div style="position:absolute;top:0;left:0;width:100%;height:100%">
some content here
</div>

Categories