Firefox drags div like it was an image - javascript

I'm using this HTML,CSS and Javascript code (in one document together if you want to test it out):
<style type="text/css">
#slider_container {
width: 200px;
height: 30px;
background-color: red;
display:block;
}
#slider {
width: 20px;
height: 30px;
background-color: blue;
display:block;
position:absolute;
left:0;
}
</style>
<script type="text/javascript" src="../../js/libs/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#slider").mousedown(function() {
$(document).mousemove(function(evnt) {
$("#test").html("sliding");
}).mouseup(function() {
$("#test").html("not sliding");
$(document).unbind("mousemove mouseup");
});});
});
</script>
<div id="test">a</div>
<div id="slider_container">
<div id="slider"></div>
</div>
Everything (surprisingly) works fine in IE, but firefox seems to totally clusterf*ck when this javascript is used. The first "slide" is okay, you drag, it says "sliding", you drop, it says "not sliding". On the second "slide" (or mousedown if you will), firefox suddenly thinks the div is an image or link and wants to drag it around.
Screenshot of the dragging:
Obviously the blue div half-positioned in the red div is the one being dragged. Windows does not capture the cursor when you take a screenshot, but it's a stop sign.
Is there someway to prevent this default behaviour?

You need to return false from the event handlers to prevent the default action (selecting text, dragging selection, etc). Based on the code posted by Crispy, Here is my solution:
$(function() {
var sliderMouseDown = false;
$("#slider").mousedown(function() {
sliderMouseDown = true;
return false;
});
$(document).mousemove(function(evnt) {
if (sliderMouseDown) {
$("#test").html("sliding");
return false;
}
});
$(document).mouseup(function() {
if (sliderMouseDown){
$("#test").html("not sliding");
sliderMouseDown = false;
return false;
}
});
});

Neat bug, after messing around with it, it appears that Firefox remembers the mousedown event on the slider and treats it as if the user had started selecting some text (hence the "stop sign" you were seeing). So then Firefox treats the next mousedown event as if the user was dragging the text away somewhere. There might be a more appropriate solution, but simply adding a
$("#slider").focus()
does the trick since then Firefox will "reset" the cursor so it won't think the user is dragging some text.
I'd also like to comment you're repeatedly binding and unbinding events (which doesn't seem to sit well with ie7 doing multiple drags). I would suggest something like the following, which binds the delegates once.
$(function() {
var sliderMouseDown = false;
$("#slider").mousedown(function() {
sliderMouseDown = true;
});
$(document).mousemove(function(evnt) {
if (sliderMouseDown) {
$("#test").html("sliding");
}
});
$(document).mouseup(function() {
if (sliderMouseDown)
{
$("#test").html("not sliding");
$("#slider").focus(); //<-- fix the FF issue to reset cursor
sliderMouseDown = false;
}
});
});

Related

mxgraph: I would like to add a button to disable/enable the graph and toolbar

I tried to disable the graph by not allowing the cells on graph with follow code.
graph.setCellsSelectable(false);
but it is not working, still can select cell, (only disabled resizing)
And for the toolbar to be disabled, I tried to remove or replace ondrag event, is that correct? In theory I think mxgraph has their own event handler for dragging of toolbar item.
mx_toolbar.appendChild(
mxUtils.button("Disable/Enable", function() {
document.querySelectorAll('.toolbar > button').addEventListener(function (e) {
e.preventDefault()
return false;
});
}
)
Hope your help. I dont mind as long as it is working solution.
Thanks
Instead of removing or modifying the event handler, you can simply overlay the area you want to disable along with css.
var toolbarContainer = document.querySelector(".toolbar");
var overlay = document.querySelector(".toolbar-overlay")
if (!overlay) {
overlay = document.createElement('div')
overlay.className = 'toolbar-overlay'
toolbarContainer.appendChild(overlay)
} else {
overlay.parentNode.removeChild(overlay)
}
Here is css for the overlay div
.toolbar-overlay {
position: absolute;
top: 0;
height: 100%;
width: 100%;
opacity: 0.4;
background: #e1e1e1;
}
Note: You should make sure the parent div of the overlay div must positioned as relative to make this css working!

Slidedown form on click

I am trying to show form when user clickes on the button. Form is showing up but there seems to be a bug for a second. form is centered when the slide up function is executing and when it is done it fits normally to the page.
Here is the js:
$(document).ready(function() {
$('.clicked').on('click', function(e) {
var current = $(e.target).next();
var show = current.hasClass('hidden');
if (show) {
current.hide();
current.removeClass('hidden');
current.slideDown('slow');
} else {
current.slideUp('slow', function() {
current.addClass('hidden');
current.slideUp('slow');
});
}
})
});
I do not think there is any bug in js code, most likely missing something in css.
Have a look here and click on blue button "Click Here" http://codepen.io/nikasv/pen/vKEEZr
Thanks.
.trip-form{
width: 100%;
overflow:hidden;
}
will do the trick even with the shaking you experience :)
You should try to set width of class "trip-form" to 100%.

Prevent user from copying text on mobile browsers

I'm trying to develop a typing speed competition using JavaScript. People should write all the words they see from a div to a textarea.
To prevent cheating (like copying the words from div) one way is check the written words only when a keyboard key is down, but I was wondering if there is a way to prevent the user from copying the text in a browser?
What I have tried so far:
Disable right click (didn't work on mobile browsers)
Show an alert using the onmousedown event in all the page (it didn't work either)
Using any libraries is OK.
You can simply make the text into an image.
<style type="text/css">
div.image {
width: 100px;
height: 100px;
background-image: url-to-your-image;
}
</style>
To generate the images you can use a server side script as in the aswers of this question
or something like this:
<?php
header("Content-type: image/png");
$im = #imagecreate(210, 30)
or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($im, 255, 255, 255);
$text_color = imagecolorallocate($im, 0, 0, 0);
imagestring($im, 4, 5, 5, "This is a test", $text_color);
imagepng($im);
imagedestroy($im);
?>
Test here
You can prevent the user from actually selecting the text so it can not be copied - however I'd still combine this with paste detection as others recommended
.noselect {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
<p>this can be selected</p>
<p class="noselect">this can NOT be selected</p>
But the user can still open the page source and copy it from there.
One crazy way of doing this is, laying out another absolutely positioned element on top of this. But this will disallow clicking of links too! May be you can do it with position: relative and a higher z-index.
.content {position: relative;}
.content .mask {position: absolute; z-index: 1; width: 100%; height: 100%;}
.content a {position: relative; z-index: 3;}
<div class="content">
<div class="mask"></div>
<p>Pages that you view in incognito tabs won’t stick around in your browser’s history, cookie store or search history after you’ve closed <strong>all</strong> of your incognito tabs. Any files that you download or bookmarks that you create will be kept. Learn more about incognito browsing</p>
</div>
Try using the touch or longpress events.
<!DOCTYPE html>
<html>
<head>
<script>
function absorbEvent_(event) {
var e = event || window.event;
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
return false;
}
function preventLongPressMenu(node) {
node.ontouchstart = absorbEvent_;
node.ontouchmove = absorbEvent_;
node.ontouchend = absorbEvent_;
node.ontouchcancel = absorbEvent_;
}
function init() {
preventLongPressMenu(document.getElementById('theimage'));
}
</script>
</head>
<body onload="init()">
<img id="theimage" src="http://www.google.com/logos/arthurboyd2010-hp.jpg" width="400">
</body>
</html>
Source
Try putting a transparent div over the text.
I have used jQuery here.
That should work.
var position = $('#textInHere').position();
$('#noClickThroughThis').css({
height: ($('#textInHere').height()),
width: ($('#textInHere').width()),
position: 'absolute',
top: position.top,
left: position.left,
'z-index': 100
});
Here is a fiddle
http://jsfiddle.net/lacrioque/tc4bwejn/
It's easy to disable the paste feature by using jQuery. For example, if you have an edit field like this one:
<p id='someInput' contenteditable='true'>Here is the text</p>
Then, this piece of jQuery code will disable the pasting feature on it:
$('#someInput').on('paste', function(e) {
return false;
});
A good way to work out if a user is cheating is to compare the current input length to the last input length. You can use a data attribute to store the previous value (or length):
<textarea class="typing-only" data-temp=""></textarea>
jQuery:
$(document).on('input', '.typing-only', function(){
if((this.value.length - 1) > $(this).data('temp').length){
alert('Cheat!');
}
$(this).data('temp', this.value);
});
JSFiddle demo
pointer-events: none
CSS pointer-events allows you to control the interaction between an element and the mouse. When set to none, the element is never the target of mouse events.
MDN definition page
You can try using :after tag and styling it with content: "Text"; in css, AFAIK you cannot select :before and :after's content.
Thanks for your amazing solutions. I tested all of them, and in short some of them worked only on a PC, some only on Chrome and Firefox and some only on Safari, but unfortunately none of them worked 100%.
Although #Max answer might be safest, I didn't tag with PHP in the question because if I use this solution dealing with answers, it will be hard because I don't have access to words on the client side!
So the ultimate solution I came with was combining all of the provided answers plus some new methods (like clearing the clipboard every second) into a jQuery plugin. Now it works on multiple elements too and worked 100% on PC browsers, Firefox, Chrome, and Safari.
What this plugin does
Prevent pasting (optional)
Clearing clipboard (looks like it doesn't work well)
Absorbs all touch events
Disable right click
Disable user selections
Disable pointer events
Add a mask with a z-index inside any selected DOM
Add a transparent div on any selected DOM
A jsFiddle:
(function($) {
$.fn.blockCopy = function(options) {
var settings = $.extend({
blockPasteClass : null
}, options);
if(settings.blockPasteClass){
$("." + settings.blockPasteClass ).bind('copy paste cut drag drop', function (e) {
e.preventDefault();
return false;
});
}
function style_appender(rule){
$('html > head').append($('<style>'+rule+'</style>'));
}
function html_appender(html){
$("body").append(html);
}
function clearClipboard() {
var $temp = $("#bypasser");
$temp.val("You can't cheat !").select();
document.execCommand("copy");
}
function add_absolute_div(id) {
html_appender("<div id='noClick"+id+"' onclick='return false;' oncontextmenu='return false;'> </div>");
}
function absorbEvent_(event) {
var e = event || window.event;
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
return false;
}
function preventLongPressMenu(node) {
node.ontouchstart = absorbEvent_;
node.ontouchmove = absorbEvent_;
node.ontouchend = absorbEvent_;
node.ontouchcancel = absorbEvent_;
}
function set_absolute_div(element,id){
var position = element.position();
var noclick = "#noClick" + id;
$(noclick).css({
height: (element.height()),
width: (element.width()),
position: 'absolute',
top: position.top,
left: position.left,
'z-index': 100
})
}
$("body").bind("contextmenu", function(e) {
e.preventDefault();
});
//Append needed rules to CSS
style_appender(
"* {-moz-user-select: none !important; -khtml-user-select: none !important; -webkit-user-select: none !important; -ms-user-select: none !important; user-select: none !important; }"+
".content {position: relative !important; }" +
".content .mask {position: absolute !important ; z-index: 1 !important; width: 100% !important; height: 100%!important;}" +
".content a {position: relative !important; z-index: 3 !important;}"+
".content, .content .mask{ pointer-events: none;}"
);
//Append an input to clear the clipboard
html_appender("<input id='bypasser' value='nothing' type='hidden'>");
//Clearing clipboard Intervali
setInterval(clearClipboard,1000);
var id = 1;
return this.each( function() {
//Preventing using touch events
preventLongPressMenu($(this));
//Add CSS preventer rules to selected DOM & append mask to class
$(this).addClass("content").append("<div class='mask'></div>");
//Append an absolute div to body
add_absolute_div(id);
//Set position of the div to selected DOM
set_absolute_div($(this),id);
id++;
});
}
}(jQuery));
Usage
$(document).ready(function(){
$(".words").blockCopy({
blockPasteClass : "noPasting"
});
});
HTML for demo:
<div class="words">Test1: Can you copy me or not?</div><br>
<div class="words">Test2: Can you <br> copy me or not?</div><br>
<textarea class="words">Test3: Can you <br>copy me or not?</textarea><br>
<textarea class="noPasting" placeholder="Test1: Paste content if you can" ></textarea><br>
<textarea class="noPasting" placeholder="Test2: Paste content if you can" ></textarea>
Let me know your opinions. Thanks.
Sources
Answers to this question
Copy text to clipboard
Add CSS rule using jQuery
A simpler solution than the accepted one would be to simply use a canvas element with filltext
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.fillText("Can't copy this", 5, 30);
<canvas id="myCanvas"></canvas>
JSFiddle example
You can return false on jQuery's cut copy paste events.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).on("cut copy paste", function(event){
return false;
});
</script>
<textarea>Try to copy my text</textarea>

Keydown event not fired when pressing escape in fullscreen in Chrome/Firefox

I have this website, which is my next portfolio site:
http://lantosistvan.com/temp/viewport-images/
On the bottom right corner, I have an anchor tag, which is triggering the next javascript:
$(".expand").on("click", function() {
$(document).toggleFullScreen();
$("#header-container, #footer-container").toggleClass('toggle-display');
$("header, footer").toggleClass('toggle-height');
$("a.expand").toggleClass('toggle-bottom');
});
$(window).on("keydown", function(e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 27, 122) {
$("#header-container, #footer-container").removeClass('toggle-display');
$("header, footer").removeClass('toggle-height');
$("a.expand").removeClass('toggle-bottom')
}
});
The first code will trigger "jquery.fullscreen 1.1.4" .js by Klaus Reimer: https://github.com/kayahr/jquery-fullscreen-plugin
And the next line will add a class in css "toggle-display" which is hide the "#header-container" and "#footer-container". "Toggle-height" gives new height for the "header" and "footer" (30px), and "toggle-bottom" will give new right and bottom margin for the button.
This works great, if I toggle with the button. However, if someone using the ESC (in Firefox) or ESC and F11 (in Chrome) buttons, the site escaping from Full Screen, but the injected CSS changes remain untouched. This will break the whole experience.
So I made the second code group, where I remove the classes, when someone press ESC or F11.
The problem:
In Firefox, F11 works great! It's deleting the classes and because of that, the
vertical image height javascript also maintain the image heights and
aspect ratios without problem.
BUT if you press ESC, it escapes from fullscreen, but not deleting
the classes. You need to press again ESC or F11, to run the code. BUT
THAN, jquery.fullscreen is still runs (because wasn't any turn off
call). If you press second time the same key, the images vertically
simple not fitting into the viewport UNTIL you made changes on
browser viewport size somehow (for example: go into window mode and
change the browser size).
Chrome have the same problem, but because Chrome enters to native
fullscreen with F11 too, the problem also appears.
If you click on the bottom right button, press ESC and than press the button again, the function turned. Now it will enter to fullscreen, just like if you press F11. I don't have problem if someone enter to fullscreen with F11 and he can see the whole site. I don't want to restrict my users in options. It's good for me that F11 untouched.
Is there any solution, where native fullscreen APIs will trigger my javascript lines on the first place? When I leave fullscreen?
UPDATE 2013.09.14.
I think It's a Webkit related issue. Why is it working with not native exit key in Firefox (F11) but not with native exit key (ESC), even if I was in native fullscreen mode all the time...? Can we somehow trick that?
UPDATE 2013.09.15.
By koala_dev:
$(".expand").on("click", function() {
$(document).toggleFullScreen();
});
$(document).on("fullscreenchange", function() {
if($(document).fullScreen()){
//Just went into fullscreen
$("#header-container, #footer-container").addClass('toggle-display');
$("header, footer").addClass('toggle-height');
$("a.expand").addClass('toggle-bottom');
}else{
//Just exit fullscreen
$("#header-container, #footer-container").removeClass('toggle-display');
$("header, footer").removeClass('toggle-height');
$("a.expand").removeClass('toggle-bottom');
}
});
UPDATE 2013.09.16 - SOLUTION!
Didn't helped to call atmeretezo() inside fullscreenchange event, so I made a little search. It turns out there is a :fullscreen CSS pseudo-class! :)
https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
http://www.sitepoint.com/html5-full-screen-api/
So I replaced the js with this:
// https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
// http://www.sitepoint.com/html5-full-screen-api/
$(document).ready(function(){
function toggleFullScreen() {
if (!document.fullscreenElement && // alternative standard method
!document.mozFullScreenElement && !document.webkitFullscreenElement) { // current working methods
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullscreen) {
document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
}
} else {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
}
}
$(".expand").on("click", function() {
toggleFullScreen();
});
});
An I added these lines into CSS:
/* EXPAND */
:-webkit-full-screen #header-container { display: none; visibility: hidden; }
:-webkit-full-screen #footer-container { display: none; visibility: hidden; }
:-moz-full-screen #header-container { display: none; visibility: hidden; }
:-moz-full-screen #footer-container { display: none; visibility: hidden; }
:fullscreen #header-container { display: none; visibility: hidden; }
:fullscreen #footer-container { display: none; visibility: hidden; }
:-webkit-full-screen header { height: 30px; }
:-webkit-full-screen footer { height: 30px; }
:-moz-full-screen header { height: 30px; }
:-moz-full-screen footer { height: 30px; }
:fullscreen header { height: 30px; }
:fullscreen footer { height: 30px; }
:-webkit-full-screen a.expand { bottom: 5px; }
:-moz-full-screen a.expand { bottom: 5px; }
:fullscreen a.expand { bottom: 5px; }
/* EXPAND */
You can't order more div into one line, otherwise not will work (I don't know why, some reason the browsers will ignore the code than).
And it's works perfectly! F11 untouched, Chrome, Firefox resizing the images perfectly in native fullscreen API mode and the CSS code modified only for full screen!
You should use the notification event provided by the plugin to alert of a change in the fullscreen state:
$(document).on("fullscreenchange", function() {
if($(document).fullScreen()){
//Just went into fullscreen
$("#header-container, #footer-container").addClass('toggle-display');
$("header, footer").addClass('toggle-height');
$("a.expand").addClass('toggle-bottom');
}else{
//Just exit fullscreen
$("#header-container, #footer-container").removeClass('toggle-display');
$("header, footer").removeClass('toggle-height');
$("a.expand").removeClass('toggle-bottom');
}
});
You may even get away with doing this without the if/else and using just toggleClass instead of add/remove

jquery overlay background dimming doesn't go away on IE9 after overlay dismissed

Let me preface this by saying that I'm new to jquery and fairly new to javascript.
I searched around a bit and found a overlay tutorial I was able to follow and at this point I don't even remember where I got it. I've got the following that works (almost):
function showOverlayBox() {
//if box is not set to open then don't do anything
if( isOpen == false ) return;
// set the properties of the overlay box, the left and top positions
$('.overlayBox').css({
display:'block',
left:($(window).width() - $('.overlayBox').width()) / 2,
top:($(window).height() - $('.overlayBox').height()) / 2 -20,
position:'absolute'
});
// set the window background for the overlay. i.e the body becomes darker
$('.bgCover').css({
display:'block',
width: $(window).width(),
height:$(window).height()
});
}
function doOverlayOpen() {
//set status to open
isOpen = true;
showOverlayBox();
$('.bgCover').css({opacity:0}).animate({opacity:0.5, backgroundColor:'#000'});
// dont follow the link : so return false.
return false;
}
function doOverlayClose() {
//set status to closed
isOpen = false;
$('.overlayBox').css( 'display', 'none' );
// now animate the background to fade out to opacity 0
// and then hide it after the animation is complete.
$('.bgCover').animate({opacity:0}, null, null, $(this).hide(););
}
<style type="text/css">
body { font:76% verdana; }
.bgCover { background:#000; position:absolute; left:0; top:0; display:none; overflow:hidden }
.overlayBox {
border:5px solid #09F;
position:absolute;
display:none;
width:500px;
height:300px;
background:#fff;
overflow: scroll;
}
.overlayContent {
padding:10px;
}
.closeLink {
float:right;
color:red;
}
a:hover { text-decoration:none; }
h2 {
padding:5px;
margin:0;
}
</style>
<div class="bgCover"> </div>
<div class="overlayBox">
<div class="overlayContent">
Close
</div>
</div>
Launch Window
<script type="text/javascript">
// if window is resized then reposition the overlay box
$(window).bind('resize',showOverlayBox);
// activate when the link with class launchLink is clicked
$('a.launchLink').click( doOverlayOpen );
// close it when closeLink is clicked
$('a.closeLink').click( doOverlayClose );
</script>
This runs fine for me in a standalone page. However, for some reason when I put this into the page I need it on, when I click the close on the overlay box, bgCover doesn't go away. This happens in IE9 but not in FF 3.6.10. If i comment out the line:
$('.bgCover').css({opacity:0}).animate({opacity:0.5, backgroundColor:'#000'});
in doOverlayOpen, it works as expected except of course that the .bgCover is all black and not transparent (I'm guessing this is because the animation doesn't ever happen).
If I replace the function call in the doOverlayClose animate call (currently just executing $(this).hide();) with a function, I can see that it never gets called. example:
function doOverlayClose() {
//set status to closed
isOpen = false;
$('.overlayBox').css( 'display', 'none' );
// now animate the background to fade out to opacity 0
// and then hide it after the animation is complete.
$('.bgCover').animate({opacity:0}, null, null, testFunction);
}
function testFunction() {
alert("GotHere!");
$(this).hide();
}
The alert never fires.
It appears as though the remove line never happens on IE9 for some reason under some circumstances but I can't figure out why.
Obviously it is a difference in environment between the two pages (where it works and where it doesn't) but I'm not finding anything to tell me what exactly. Can anyone point me in the right direction of what I should be looking for?
What happends if you do not use the css?
doOverlayOpen{
...
$('.bgCover').animate({opacity:0.5, backgroundColor:'#000'});
}
doOverlayClose
...
$('.bgCover').animate({opacity:0, backgroundColor:'transparent'});
}

Categories

Resources