Firefox is not displaying image in drag and drop ghost preview - javascript

I'm trying to display ghost element instead of default browser preview for drag and drop. The problem is that in firefox image inside ghost element is not displayed while dragging. But if I drop it, and drag again the image is displayed.
So I think that this might be some sort of cache-related problem. But I can't see how I can pre-cache image in this case.
Here's the code:
//html:
<div class="parent container">
<img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />
</div>
//js:
document.querySelector(".element").addEventListener("dragstart", function(e) {
var img = document.createElement("img");
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.position = 'fixed';
div.style.top = '-1000000px';
div.style.left = '-1000000px';
div.style.border = '2px solid red';
img.src = "http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg";
img.style.width = '100px';
img.style.height = '100px';
div.appendChild(img);
document.body.appendChild(div);
e.dataTransfer.setData('text/plain', 'test');
e.dataTransfer.setDragImage(div, 0, 0);
}, false);
Fiddle:
https://jsfiddle.net/etseq5cg/5/
Steps to reproduce:
1) open fiddle/run snippet
2) try to drag sample image
Actual: you'll see an empty square with red border
Expected: square with image inside.
To reproduce it again you need to force-reload the page(ctrl+f5). That's why I think this is cache-ralated issue.
Note: I know that I should remove ghost element from DOM in dragend handler, but this is not important here.
Update:
1) the actual use-case includes view with big amount of images(~500), so it's not an option to pre-cache images via js.
2) For the ones who couldn't reproduce the issue, here's the screenshot: at first you see preview after hard reload(ctrl+f5), and then the second dragging attempt. Please note that no http requests are seen in network tab in web inspector in both cases.

I cannot see the problem when I run your jsfiddle in Firefox 53 (on Windows 7). The ghost image and the dragged image have the same URL and the ghost image is always displayed when dragging. However, I can reproduce the problem with a ghost image that has a different URL.
You could add a hidden img control to preload the ghost image. Something like this:
<div class="parent container">
<img class="element" draggable="true" src="http://the.element.image" />
<img class="imgGhost" src="http://the.ghost.image" />
</div>
According to my tests, these settings prevent the image preload in Firefox:
Hiding the element with display: none
Setting a null size (width: 0px or height: 0px)
Moving it outside of the viewport (e.g. left: -10000px)
I also did not have much success with link prefetching. However, visibility: hidden seems to work. The style of the hidden image element could be defined as:
.imgGhost {
position: absolute;
left: 0px;
top: 0px;
visibility: hidden;
}
The method can be tested for two draggable images in this jsfiddle. In the dragstart event handler, the image URL is retrieved from the hidden element:
img.src = this.parentNode.querySelector(".imgGhost").src;
but it could be hard coded. If you prefer, you could set the src attribute of the hidden image dynamically when the page is loaded. When testing in the jsfiddle, you can change the ghost image names (e.g. 225x225) before running it again, to make sure that the image was not cached.
According to your comment, preloading the image is not an option. And you are using the same image URL for the dragging ghost image. In that case, you could check this page to see if any option is preventing the reload of the image.
You could also force a repaint of the layout after adding the div control to the body in the dragstart event handler. This can be achieved by calling div.offsetHeight:
div.appendChild(img);
document.body.appendChild(div);
div.offsetHeight; // Force repaint

At css set .parent pseudo class :hover and .element background to url("/path/to/image") to fetch image at :hover of <img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" /> parent element. At dragstart event set div .className to "element".
.element {
width: 100px;
height: 100px;
background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
background-size: 100px 100px;
}
.parent:hover {
background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
background-size: 0px 0px;
}
<div class="parent container">
<img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />
</div>
<script>
function handleImage(e) {
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.position = 'fixed';
div.style.top = '-1000000px';
div.style.left = '-1000000px';
div.style.border = '2px solid red';
div.className = "element";
document.body.appendChild(div);
e.dataTransfer.setData('text/plain', 'test');
e.dataTransfer.setDragImage(div, 0, 0);
}
document.querySelector(".element")
.addEventListener("dragstart", handleImage, false);
</script>
jsfiddle https://jsfiddle.net/etseq5cg/7/

Related

Set position of <div> at runtime

On mouseover I want to move the "imgbox" to a specific absolute position (which might move it on top of the "i" image).
The second image ("newimg") loads, so that part works (including hiding it again in "onmouseout") but it's displayed below everything (like in the HTML code). It seems like setting imgbox.style.left and imgbox.style.top doesn't do anything. If I set "margin" instead, the image is displayed 200px to the right and 200px down from where it originally was (but still below everything else).
What did I miss? How do I move the "imgbox" at runtime with regular Javascript (no JQuery please!)?
function onHoverIn(url) {
var imgbox = document.getElementById("imgbox");
imgbox.style.visibility='visible';
var newimg = document.createElement("img");
newimg.src = url;
var oldimg = document.getElementById("i");
/*if(oldimg.addEventListener){ //Removed so the snippet'll run
oldimg.addEventListener('mouseout',onHoverOut,false);
} else {
oldimg.attachEvent('onmouseout',onHoverOut);
}*/
imgbox.innerHTML='';
imgbox.appendChild(newimg);
imgbox.style.left = '200px';
imgbox.style.top = '200px';
//imgbox.style.marginLeft = '200px';
//imgbox.style.marginTop = '200px';
}
#imgbox {
position : absolute;
border: 1px solid #999;
background : #FFFFFF;
filter: Alpha(Opacity=100);
visibility : hidden;
z-index : 50;
overflow : hidden;
}
<img id="i" src="https://i.pinimg.com/originals/53/02/a4/5302a4c318139bf5753c433b1f4c6aa8.jpg" alt="DP" onmouseover="onHoverIn('https://i.pinimg.com/originals/b2/1b/07/b21b0738ea390fc56a4d3efe76ab88de.jpg')">
<p>Long Teeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeext<br><br><br><br><br>END TEEEEEEEEEEEXT</p>
<div id="imgbox"></div>
Sorry, the images are pretty big, so not sure how well it'll work. I tested the code with Firefox 85.0, Chrome 88, IE and Edge by simply double-clicking the .html file and the positioning doesn't work properly in any of them.
This was quite a bit harder than I thought it would be, made some changes to your code. Hope this still works for you.
NOTE: I implemented an onHoverOut locally and noticed that when I moved my mouse around on the image it would flicker. This happens because the new image is loaded and once moving again the old image registers a onHoverOut (because you hover on top of the new image) which would then remove the new image, at which point the old image registers the onmouseover again and adds the new image. This would keep looping for as long a you move the mouse around.
function onHoverIn(url) {
var imgbox = document.getElementById("imgbox");
imgbox.style.visibility='visible';
var newimg = document.createElement("img");
newimg.src = url;
var oldimg = document.getElementById("i");
if(oldimg.addEventListener){
oldimg.addEventListener('mouseout',onHoverOut,false);
} else {
oldimg.attachEvent('onmouseout',onHoverOut);
}
//imgbox.innerHTML='';
imgbox.appendChild(newimg);
}
function onHoverOut() {
console.log('onHoverOut: not implemented');
}
.article{
width:640px;
padding:0 16px;
}
.image-box{
position:relative;
width:100%;
height:0;
/* 16:9 */
padding-top:56.25%;
overflow:hidden;
}
.image-box img{
position:absolute;
top:0;
width:100%;
}
<div class="article">
<p>content before..</p>
<div id="imgbox" class="image-box">
<img id="i" src="https://i.pinimg.com/originals/53/02/a4/5302a4c318139bf5753c433b1f4c6aa8.jpg" alt="DP" onmouseover="onHoverIn('https://i.pinimg.com/originals/b2/1b/07/b21b0738ea390fc56a4d3efe76ab88de.jpg')">
</div>
<p>content after..</p>
</div>

Chrome DIV not fully painted

I am using Chrome version 41.0.2272.118.
There is a specific DIV on the page where if I change its contents by assigning its innerHTML or innerText then another DIV on the page is corrupted.
The result of the corruption is that the corrupted DIV's right padding is no longer drawn. However the DIV takes up the same space and it has the same width according to the developer tools. Additionally the corrupted DIV's bottom border is still drawn even though there is no div above it.
Oddly even though the div has the same width any text in the div is rewrapped and sentences in it take up more lines.
Changing the innerHTML or innerText of other DIVs on the page does not result in any corruption.
Sometime a later DOM modification can trigger fixing the corrupted DIV so that its right padding is again drawn and it is rewrapped the way it was before it was corrupted.
Here is a small example of the problem:
If an absolute div is within a table
If the content of the absolute div is changed using innerHTML in an asynchronous callback
And this was done before the asynchronous callback `document.body.style.cursor = "progress";
Then all cells in the first column of the table will be painted with the wrong width for the background
HTML:
<table>
<tr>
<td>
<div class="wrapper">
<div id="twoandthree">
<div id="two">two</div>
<div id="three">three</div>
</div>
</div>
</td>
</tr>
</table>
<button id="button">update two</button>
CSS:
#twoandthree {
position:relative;
min-width:80px;
overflow:hidden;
}
#two {
position: absolute;
white-space:nowrap;
display:inline-block;
}
#three {
float: right;
position:relative;
display:inline-block;
}
table {
border-spacing: 10px;
}
.wrapper {
background: lightblue;
}
JavaScript:
var two = document.getElementById("two");
var button = document.getElementById("button");
button.addEventListener('click', function () {
document.body.style.cursor = "progress";
setTimeout(function () {
document.body.style.cursor = "";
two.innerHTML = "aaa";
}, 500);
});
I would appreciate any help with this.
Thank you
Sometimes I notice weird rendering quirks with Chrome as well. Try applying -webkit-transform: translateZ(0) to your CSS force GPU acceleration.
Here is some more info about it: http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/

image moved with 1px above on click

So, I use this Javascript for hide - show effect:
function effect(id) {
var h = document.getElementById(id);
h.style.display = ((h.style.display != 'none') ? 'none' : 'inline');
}
HTML:
<div class="div">
<img src="http://i.imm.io/1jf2j.png"/>
Home
</div>
and CSS:
.div {
background: #000;
}
.div .url {
font-size: 17px;
}
Here you can test (and edit!) the code: http://codepen.io/anon/pen/dhHiw
JSFiddle doesn't work for me.
All is good. Except when you click on image. It's moved 1px above. Should I use another image?
Where is the problem? And possible solutions. Thank you!
You are basically removing the text element. Since the <div class="div"> does not have a set height, it depends on the elements inside it. When the text is not displayed (display=none), the div will resize to only the image.
You can fix this by either setting a height for the div, or by setting visibility=hidden for the text instead of display=none. When making it hidden, it still has the same dimensions, but it's invisible instead.

mouseover show div

I haven't been able to find the answer to this anywhere.
How do you make a hidden div appear when mousing over where it would have been?
Please do not tell me how to make a link, I know how to make a link ;)
I have tried:
a.) onmouseover set visibility to visible and onmouseout set visibility to hidden
this works in 0 browsers
b.) setting borders to 0px and background transparent and innerhtml to "" onmouseout and reverting onmouseover
this works in chrome
c.) This was the most popular answer on the internet, which i knew wouldn't work, but I tried anyway: make a container div set to visible and then do visibility visible and visibility hidden for the inner div
d.) Setting opacity to 1/100 and 0
works in chrome
e.) last resort: i tried making a transparent gif and having it display onmouseout
this also failed
I haven't tried jquery's .hover but I have read that it may not work correctly.
I have no other ideas. Will somebody help, please?
If I get it right you want div element to show if you are over it and hide when the mouse is not over. If that's it you can do it only with html and css:
<head>
<style>
#outerDiv{width:100px;height:100px;background-color:blue;}
#innerDiv{width:100px;height:100px;background-color:red;display:none;}
#outerDiv:hover #innerDiv {display:block;}
</style>
</head>
<html>
<div id="outerDiv">
<div id="innerDiv">some text</div>
</div>
</html>
The outer div is always visible and when it's hovered the inner one is shown.
I think that this is going to help you: http://jsfiddle.net/eb4x9/
The mouseover event won't trigger when the div is hidden so you can detect it's position and size.
Here is the source:
HTML
<div id="foo"></div>
CSS
#foo {
width: 300px;
height: 300px;
background-color: red;
visibility: hidden;
}
JS
$(document).mousemove(function (event) {
var div = $('#foo'),
divLeft = div.offset().left,
divTop = div.offset().top,
divWidth = div.width(),
divHeight = div.height();
if ((event.pageX >= divLeft && event.pageX <= divLeft + divWidth) &&
(event.pageY >= divTop && event.pageY <= divTop + divHeight)) {
div.css('visibility', 'visible');
} else {
div.css('visibility', 'hidden');
}
});
$(document).mouseleave(function (event) {
var div = $('#foo');
div.css('visibility', 'hidden');
});
Best regards!
Try setting the display attribute of the div to 'block' along with the visibility attribute to 'visible' in your onmouseover event.
Set the display to 'none' and visibility to 'hidden' to hide.
Of course the trouble will be firing the mouse over on a hidden div.
This works in every browser I have ever used it in.
Try this, having two divs one empty and other with your content and toggling between them on mouseover
<html>
<head>
<script>
function toggle() {
var your_div = document.getElementById("your_div");
var empty_div = document.getElementById("empty_div");
if(your_div.style.display == "block") {
your_div.style.display = "none";
empty_div.style.display = "block";
}
else {
your_div.style.display = "block";
empty_div.style.display = "none";
}
}
</script>
<style>
#empty_div{width:100px; height:100px;}
#your_div{width:100px; height:100px; border: 1px solid #000fff;}
</style>
</head>
<body>
<div id="your_div" onmouseover="toggle()">xyz</div>
<div id="empty_div" onmouseover="toggle()"></div>
</body>
</html>

How to enlarge image while hover over an image?

I want to show the thumbnail image large when hover over it, similar to the one in
http://www.freelayouts.com/websites/html-templates Plz help. Any help will be appreciated.
What you need is a tooltip plugin. There are plenty of them.
Check out this list: https://cssauthor.com/jquery-css3-hover-effects/
<img class="enlarge-onhover" src="img.jpg">
...
And on the css:
.enlarge-onhover {
width: 30px;
height: 30px;
}
.enlarge-onhover:hover {
width: 70px;
height: 70px;
}
Take a look at http://fancybox.net/blog
Fancybox looks nice, uses JQuery and is highly configurable with various show/hide effects. Tutorial number 3 on this page shows you how to use it OnHover rather than OnClick
The home page http://fancybox.net/home shows some examples of the visual effect
<script>
function bigImg(x) {
x.style.height = "64px";
x.style.width = "64px";
}
function normalImg(x) {
x.style.height = "32px";
x.style.width = "32px";
}
</script>
<img onmouseover="bigImg(this)" onmouseout="normalImg(this)" border="0" src="smiley.gif" alt="Smiley" width="32" height="32">
The function bigImg() is triggered when the user mouse over the image. This function enlarges the image.
The function normalImg() is triggered when the mouse pointer is moved out of the image. That function sets the height and width of the image back to normal.

Categories