I'm building a gallery in ReactJs and have draggable thumbs below main image.
The problem is, whenever I drag a thumb, its link url drags with the mouse.
http://prntscr.com/76kfrk
Is it possible to hide the url on drag?
Preferably using with Vanilla Js
Since it's the title of the a-tag (you didn't set an alt title, so it displays the url), you should be able to hide it with the following bit of Javascript:
var elements = document.getElementsByTagName('a');
for (var i = 0, len = elements.length; i < len; i++)
{
elements[i].removeAttribute('title');
}
This can be prevented with a preventDefault on the onMouseDown event.
//React Component
someFunc: function(e) {
e.preventDefault();
},
render: function() {
return (<img src="somepicture.jpg" onMouseDown={this.someFunc} />)
}
As pointed out below, the only way I know to prevent this is by calling event.preventDefault().
If you are using a special plugin for the slider then I would suggest you to take a look into its docs to see how you can receive the mousedown event when the user starts the drag.
This can also be prevented by using the CSS property -webkit-user-drag: none; for elements.
Related
Forgive me for my silly question, I'm a beginner :/
For some reason, I can't use Jquery due to some stuff with Divi theme on Wordpress.
I need to change CSS class to some links so that they will change color if selected
(these links reveals different divs contents)
I've tried this:
function linkcolor() {
document.getElementById(arguments[0]).className='serveminus';
for(var i=1; i< arguments.length-1; i++) {
document.getElementById(arguments[i]).className='serve';
}
}
When I call the function I'll add the anchors' ids as parameters.
The first one will be shown as "selected" (serveminus) one while the other will be grayed out (serve).
Somehow I've got this working but I need to have this other feature:
When a link is already selected and it has the "serveminus" class, if clicked again, the class changes back to "serve".
If I add the following condition I guess it generates a nonsense loop....
if (document.getElementById(arguments[0]).className='serveminus') {
document.getElementById(idlink).className='serve';
} else {
Sounds like you need to set an onClick event listener:
https://developer.mozilla.org/en-US/docs/Web/API/EventListener
Pseudo code might be:
if link is clicked and link is selected
set event listener on link
onClick change class to 'serve'
remove event listener
Sounds like you need an eventListener that will toggle the class, I would first have all the links that you want to apply this style to in an variable. And apply the code block below .
var linkArray = doucument.querySelectorAll('navigationLinks');
// Example-> var linkArray = document.querySelectorAll('nav ul li a');
for(var i = 0; i < linkArray.length; i++) {
linkArray[i].addEventListener("click", e => {
e.target.classList.toggle('classToToggle');
})
}
I've been trying to find code to simulate mouseover in Chrome but even though the "mouseover" listener gets fired, the CSS "hover" declaration is never set!
I tried also doing:
//Called within mouseover listener
theElement.classList.add("hover");
But nothing seems to change the element to what is declared in its hover declaration.
Is this possible?
You can't. It's not a trusted event.
Events that are generated by the user agent, either as a result of user interaction, or as a direct result of changes to the DOM, are trusted by the user agent with privileges that are not afforded to events generated by script through the DocumentEvent.createEvent("Event") method, modified using the Event.initEvent() method, or dispatched via the EventTarget.dispatchEvent() method. The isTrusted attribute of trusted events has a value of true, while untrusted events have a isTrusted attribute value of false.
Most untrusted events should not trigger default actions, with the exception of click or DOMActivate events.
You have to add a class and add/remove that on the mouseover/mouseout events manually.
You can simulate the mouseover event like this:
HTML
<div id="name">My Name</div>
JavaScript
var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
console.log('Event triggered');
});
var event = new MouseEvent('mouseover', {
'view': window,
'bubbles': true,
'cancelable': true
});
element.dispatchEvent(event);
Background
I stumbled upon this question while trying to write automated tests, to verify, that a certain set of elements on a given page all receive have the some set of css properties set by the css for on hover events.
While the above answer perfectly explains, why it is not possible to simply trigger the hover event by JS and then probe some css value of interest, it does answer the initial question "How do I simulate a mouseover in pure JavaScript that activates the CSS “:hover”?" only partly.
Disclaimer
This is not a performant solution. We use it only for automated testing, where performance is not a concern.
Solution
simulateCssEvent = function(type){
var id = 'simulatedStyle';
var generateEvent = function(selector){
var style = "";
for (var i in document.styleSheets) {
var rules = document.styleSheets[i].cssRules;
for (var r in rules) {
if(rules[r].cssText && rules[r].selectorText){
if(rules[r].selectorText.indexOf(selector) > -1){
var regex = new RegExp(selector,"g")
var text = rules[r].cssText.replace(regex,"");
style += text+"\n";
}
}
}
}
$("head").append("<style id="+id+">"+style+"</style>");
};
var stopEvent = function(){
$("#"+id).remove();
};
switch(type) {
case "hover":
return generateEvent(":hover");
case "stop":
return stopEvent();
}
}
Explanation
generateEvent reads all css files, , replaces :hover with an empty string and applies it. This has the effect, that all :hover styles are applied. Now one can probe for a howered style and set back to initial state by stopping the Simulation.
Why do we apply the hover effect for the whole document and not just for the element of interest by getting the from the sheets and then perform a element.css(...)?
Done as that, the style would be applied inline, this would override other styles, which might not be overriden by the original css hover-style.
How would I now simulate the hover for a single element?
This is not performant, so better don't. If you must, you could check with the element.is(selectorOfInterest) if the style applies for your element and only use those styles.
Example
In Jasmine you can e.g. now perform:
describe("Simulate CSS Event", function() {
it("Simulate Link Hover", function () {
expect($("a").css("text-decoration")).toBe("none");
simulateCssEvent('hover');
expect($("a").css("text-decoration")).toBe("underline");
simulateCssEvent('stop');
expect($("a").css("text-decoration")).toBe("none");
});
});
What I usually do in this case is adding a class using javascript.. and attaching the same CSS as the :hover to this class
Try using
theElement.addEventListener('onmouseover',
function(){ theElement.className += ' hovered' });
Or for older browsers:
theElement.onmouseover = function(){theElement.className += ' hovered'};
you will of course have to use onmouseout to remove the "hovered" class when you leave the element...
You can use pseudo:styler, a library which can apply CSS pseudo-classes to elements.
(async () => {
let styler = new PseudoStyler();
await styler.loadDocumentStyles();
document.getElementById('button').addEventListener('click', () => {
const element = document.getElementById('test')
styler.toggleStyle(element, ':hover');
})
})();
Disclaimer: I am a coauthor of this library. We designed it to additionally support cross-origin stylesheets, specifically for use in Chrome extensions where you likely lack control over the CSS rules of the page.
I'm assuming you want to inspect the CSS after dom manipulation, but as soon as you move your mouse back to the devtools, the event isn't active on that html element anymore. You probably would like to have something like the :hover option in devtools for your javascript events. That doesn't exist, but you can simulate it.
Open your devtools and click in it to make it active.
Trigger the event on the element you're interested in.
Without moving the mouse, open the devtools command panel with ctrl + shift + p and select 'disable javascript' with your keyboard.
Since javascript is disabled, it doesn't get the chance to modify the element(s) back again. You can go to the devtools and inspect the css and html as if you were hovering, clicking or doing something else with it. After you're done, go to the command panel again and select 'enable javascript'.
I've been trying to find code to simulate mouseover in Chrome but even though the "mouseover" listener gets fired, the CSS "hover" declaration is never set!
I tried also doing:
//Called within mouseover listener
theElement.classList.add("hover");
But nothing seems to change the element to what is declared in its hover declaration.
Is this possible?
You can't. It's not a trusted event.
Events that are generated by the user agent, either as a result of user interaction, or as a direct result of changes to the DOM, are trusted by the user agent with privileges that are not afforded to events generated by script through the DocumentEvent.createEvent("Event") method, modified using the Event.initEvent() method, or dispatched via the EventTarget.dispatchEvent() method. The isTrusted attribute of trusted events has a value of true, while untrusted events have a isTrusted attribute value of false.
Most untrusted events should not trigger default actions, with the exception of click or DOMActivate events.
You have to add a class and add/remove that on the mouseover/mouseout events manually.
You can simulate the mouseover event like this:
HTML
<div id="name">My Name</div>
JavaScript
var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
console.log('Event triggered');
});
var event = new MouseEvent('mouseover', {
'view': window,
'bubbles': true,
'cancelable': true
});
element.dispatchEvent(event);
Background
I stumbled upon this question while trying to write automated tests, to verify, that a certain set of elements on a given page all receive have the some set of css properties set by the css for on hover events.
While the above answer perfectly explains, why it is not possible to simply trigger the hover event by JS and then probe some css value of interest, it does answer the initial question "How do I simulate a mouseover in pure JavaScript that activates the CSS “:hover”?" only partly.
Disclaimer
This is not a performant solution. We use it only for automated testing, where performance is not a concern.
Solution
simulateCssEvent = function(type){
var id = 'simulatedStyle';
var generateEvent = function(selector){
var style = "";
for (var i in document.styleSheets) {
var rules = document.styleSheets[i].cssRules;
for (var r in rules) {
if(rules[r].cssText && rules[r].selectorText){
if(rules[r].selectorText.indexOf(selector) > -1){
var regex = new RegExp(selector,"g")
var text = rules[r].cssText.replace(regex,"");
style += text+"\n";
}
}
}
}
$("head").append("<style id="+id+">"+style+"</style>");
};
var stopEvent = function(){
$("#"+id).remove();
};
switch(type) {
case "hover":
return generateEvent(":hover");
case "stop":
return stopEvent();
}
}
Explanation
generateEvent reads all css files, , replaces :hover with an empty string and applies it. This has the effect, that all :hover styles are applied. Now one can probe for a howered style and set back to initial state by stopping the Simulation.
Why do we apply the hover effect for the whole document and not just for the element of interest by getting the from the sheets and then perform a element.css(...)?
Done as that, the style would be applied inline, this would override other styles, which might not be overriden by the original css hover-style.
How would I now simulate the hover for a single element?
This is not performant, so better don't. If you must, you could check with the element.is(selectorOfInterest) if the style applies for your element and only use those styles.
Example
In Jasmine you can e.g. now perform:
describe("Simulate CSS Event", function() {
it("Simulate Link Hover", function () {
expect($("a").css("text-decoration")).toBe("none");
simulateCssEvent('hover');
expect($("a").css("text-decoration")).toBe("underline");
simulateCssEvent('stop');
expect($("a").css("text-decoration")).toBe("none");
});
});
What I usually do in this case is adding a class using javascript.. and attaching the same CSS as the :hover to this class
Try using
theElement.addEventListener('onmouseover',
function(){ theElement.className += ' hovered' });
Or for older browsers:
theElement.onmouseover = function(){theElement.className += ' hovered'};
you will of course have to use onmouseout to remove the "hovered" class when you leave the element...
You can use pseudo:styler, a library which can apply CSS pseudo-classes to elements.
(async () => {
let styler = new PseudoStyler();
await styler.loadDocumentStyles();
document.getElementById('button').addEventListener('click', () => {
const element = document.getElementById('test')
styler.toggleStyle(element, ':hover');
})
})();
Disclaimer: I am a coauthor of this library. We designed it to additionally support cross-origin stylesheets, specifically for use in Chrome extensions where you likely lack control over the CSS rules of the page.
I'm assuming you want to inspect the CSS after dom manipulation, but as soon as you move your mouse back to the devtools, the event isn't active on that html element anymore. You probably would like to have something like the :hover option in devtools for your javascript events. That doesn't exist, but you can simulate it.
Open your devtools and click in it to make it active.
Trigger the event on the element you're interested in.
Without moving the mouse, open the devtools command panel with ctrl + shift + p and select 'disable javascript' with your keyboard.
Since javascript is disabled, it doesn't get the chance to modify the element(s) back again. You can go to the devtools and inspect the css and html as if you were hovering, clicking or doing something else with it. After you're done, go to the command panel again and select 'enable javascript'.
I'm using the excellent jQuery knob plugin. However, I need to dynamically enable/disable the element depending on user input. There is support for having a disabled state on page load which have the effect that no mouse (or touch) events are bound to the canvas element. Does anyone know how to resolve this issue, that is, how to (after page load) bind and unbind these mouse event listeners?
Ideally I would like to do something like this (on a disabled knob)
$('.button').click(function() {
$('.knob').enable();
});
Edit:
I ended up rewriting the source which binds/unbinds the mouse and touch events. The solution is not perfect so I leave the question open if someone perhaps have a better (cleaner) solution.
html
<input class="knobSlider" data-readOnly="true">
<button id="testBtn">clickHere</button>
script
in doc ready,
$(".knobSlider").knob();
$("#testBtn").click(function(){
$(".knobSlider").siblings("canvas").remove();
if($(".knobSlider").attr("data-readOnly")=='true'){
$(".knobSlider").unwrap().removeAttr("data-readOnly readonly").data("kontroled","").data("readonly",false).knob();
}
else{
$(".knobSlider").unwrap().attr("data-readOnly",true).data("kontroled","").data("readonly",true).knob();
}
});
For reference you can use my jsfiddle link > http://jsfiddle.net/EG4QM/ (check this in firefox, because of some external resource load problem in chrome)
If someone doesn't like how the accepted answer destroys and recreates the internal canvas element, then checkout my approach:
https://jsfiddle.net/604kj5g5/1/
Essentially, check the draw() implementation (I also recommend listening on value changes in the draw method instead of the change and release, which work for and click and mousewheel events respectively, which imo is inconvenient).
var $input = $("input");
var knobEnabled = true;
var knobPreviousValue = $input.val();
$input.knob({
draw: function () {
if (knobPreviousValue === $input.val()) {
return;
}
if (!knobEnabled) {
$input.val(knobPreviousValue).trigger("change");
return;
}
knobPreviousValue = $input.val();
console.log($input.val());
},
});
Try this to disable the control.
I'm still trying to find a way to enable it back
$("#btnDisable").click(function(){
$("#knob").off().prev().off();
});
$('a').click(function(e){return false;});
It successfully disables links almost everywhere but does not work on the links found in the tooltip-popups on the topic tags on this site (SO). I looked at the DOM and they are indeed <a> tags.
How come?
Is there a more robust way to force my user to stay on the current page? (This is for a bookmarklet where I graphically manipulate the DOM so I need to be able to click and drag everything, including links.)
I know that even if I can disable the regular click functionality on all anchors it won't do anything for any navigation triggered by other click callbacks on other tags.
try with .on - in e.g. SO sites those links are created later then your event attached
$(document).on('click', 'a', function(e) {
return false;
});
A technique I've employed before is to place an invisible absolutely-positioned element over the entire document. This is actually employed by Firebug Lite to allow the Element Inspector to intercept any clicks.
All you need to worry about then is attaching your event listener to your absolutely-positioned element and figuring out what element was under the mouse when you clicked. Luckily, all modern browsers implement a method to discern this: document.elementFromPoint. There are a few differences between implementations; here's the method I usually use (unfortunately feature detection's a bit tricky for this, so I'm doing browser detection):
var scrollIsRelative = !($.browser.opera || $.browser.safari && $.browser.version < "532");
$.fromPoint = function(x, y) {
if(!document.elementFromPoint) return null;
if(scrollIsRelative)
{
x -= $(document).scrollLeft();
y -= $(document).scrollTop();
}
return document.elementFromPoint(x, y);
};
Attach a click event listener to your absolutely-positioned div and on click, hide your div and call this method to get the element, then show your div again. Example:
$('#hugeDiv').on('click', function(ev) {
var x = ev.pageX;
var y = ev.pageY;
$(this).hide();
var el = $.fromPoint(x, y);
$(this).show();
//do stuff with el
});
It would appear the solution is
window.onbeforeunload = function() {
return "Are you sure you want to navigate away?";
}
A right proper use of an event system if I would say so myself.
The original scope of the question was not wide enough. This solves the problem that led to my question.