Try to do something hide alert window by pressing spacebar or any key in keyboard.
existing only able to do using click listener.
$('.alertWindow1').click(function (event) {
s.hide();
});
Trying this code but not able function
$('.alertWindow1').keypress(function (event) {
if (event.keyCode == 27) {
s.hide();
}
});
This is full existing code, try to add hide the alert window using keypress
<script type="text/javascript">
jQuery.extend({
alertWindow: function (e, n) {
var e = e, r; n === undefined ? r = "#00a8b7" : r = n;
if ($("body").find(".alertWindow1").length === 0) {
var i = '<div class="alertWindow1" style="width: 100%;height: 100%; background:rgba(0,0,0,0.5);position: fixed; left:0px; top: 0px; z-index: 9999;"><div id="successImg" style="margin-top:200px;margin-left:20px;text- align:center;" >' + "</div>" + "</div>";
$("body").append(i);
var s = $(".alertWindow1");
var ddbarcode = $('#hidbarcode').val();
if (ddbarcode != "") {
displayCard(ddbarcode);
}
$('.alertWindow1').click(function (event) {
s.hide();
});
}
else {
$(".alertWindowContent").text(e), $(".alertWindow1").show(), setTimeout(function () {
$(".alertWindow1").hide();
}, 1000);
}
}
})
</script>
You need to think about where the event is firing, and where it will bubble to.
Key events start wherever the focus is.
The div you are adding to the document isn’t focusable. It has no descendants that are focusable. Even if it did, you haven’t done anything to move the focus from where it is now to such an element.
So the key event will start where the focus is now and bubble up until it hits the document object without even passing through that div. This means it never passes anywhere that you listen for it.
You can listen on the document object instead.
Related
I am trying to get the down arrow keyup event to fire automagically using jQuery. The annotorious/seadragon combination has a listener that opens all preconfigured tags when I press the down arrow.
I have written jQuery code to find the input field, put focus on it and then trigger the keyup event.
function triggerDownArrowOnInput() {
$("[id^=downshift][id$=input]").each(function(index) {
// There should only be 1, but let's not assume.
console.log(index);
if (index == 0) {
console.log("Found an input: " + $(this).attr("id"))
$(this).focus();
var event = jQuery.Event("keyup");
event.keyCode = event.which = 40; // down arrow
$(this).trigger(event);
} else {
console.log("Multiple elements found that match the id: " + $(this).attr("id"));
} // if
})
} // triggerDownArrowOnInput
The focus is working great, but not the trigger. If I manually hit the down arrow key, then the preconfigured tags all appear:
I have tried "keyCode" and "which" separately.
I have tried triggering $(this).keyup(event).
I have tried putting in a delay between the focus call and the trigger/keyup call.
I have tried calling $(document).trigger(event).
I thought maybe I was sending the event to the wrong element, but it appears (going through Dev tools) that only the Input field and the document have the listeners enabled.
No matter what I do, I can't get the event to fire. Any ideas?
Thanks.
I think I've got this working without jQuery, using a KeyboardEvent and dispatchEvent. With my tests I don't think you need the focus before hand either because it's an event on the element, but worth testing this on your application.
function triggerDownArrowOnInput() {
$("[id^=downshift][id$=input]").each(function(index) {
// There should only be 1, but let's not assume.
console.log(index);
if (index == 0) {
console.log("Found an input: " + $(this).attr("id"))
$(this).focus();
this.dispatchEvent(new KeyboardEvent('keyup',{'keyCode': 40, 'key':'ArrowDown', 'code':'ArrowDown'}));
} else {
console.log("Multiple elements found that match the id: " + $(this).attr("id"));
}
})
}
Have you tried keydown?
var e = jQuery.Event("keydown");
e.which = 40;
e.keyCode = 40
$(this).trigger(e);
function triggerDownArrowOnInput() {
$("[id^=downshift][id$=input]").each(function(index) {
// There should only be 1, but let's not assume.
console.log(index);
if (index == 0) {
console.log("Found an input: " + $(this).attr("id"))
$(this).focus();
var event = jQuery.Event("keydown");
event.keyCode = event.which = 40;
$(this).trigger(event);
} else {
console.log("Multiple elements found that match the id: " + $(this).attr("id"));
}
})
} // triggerDownArrowOnInput
I was able to get the event to fire, but still wasn't able to open the menu on focus. I ended up having to create a development environment for:
recogito/recogito-client-core
recogito/recogito-js
recogito/annotorious
recogito/annotorious-openseadragon
I then modified Autocomplete.jsx in recogito/recogito-client-core, added an OnFocus listener and then added the following code:
const onFocus = evt => {
if (!isOpen) {
this.setState({ inputItems: this.props.vocabulary }); // Show all options on focus
openMenu()
} // if
} // onFocus
Way more than I wanted to do, but it is working now.
I have searched for a good solution everywhere, yet I can't find one which does not use jQuery.
Is there a cross-browser, normal way (without weird hacks or easy to break code), to detect a click outside of an element (which may or may not have children)?
Add an event listener to document and use Node.contains() to find whether the target of the event (which is the inner-most clicked element) is inside your specified element. It works even in IE5
const specifiedElement = document.getElementById('a')
// I'm using "click" but it works with any event
document.addEventListener('click', event => {
const isClickInside = specifiedElement.contains(event.target)
if (!isClickInside) {
// The click was OUTSIDE the specifiedElement, do something
}
})
var specifiedElement = document.getElementById('a');
//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
alert('You clicked inside A')
} else {
alert('You clicked outside A')
}
});
div {
margin: auto;
padding: 1em;
max-width: 6em;
background: rgba(0, 0, 0, .2);
text-align: center;
}
Is the click inside A or outside?
<div id="a">A
<div id="b">B
<div id="c">C</div>
</div>
</div>
You need to handle the click event on document level. In the event object, you have a target property, the inner-most DOM element that was clicked. With this you check itself and walk up its parents until the document element, if one of them is your watched element.
See the example on jsFiddle
document.addEventListener("click", function (e) {
var level = 0;
for (var element = e.target; element; element = element.parentNode) {
if (element.id === 'x') {
document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
return;
}
level++;
}
document.getElementById("out").innerHTML = "not x clicked";
});
As always, this isn't cross-bad-browser compatible because of addEventListener/attachEvent, but it works like this.
A child is clicked, when not event.target, but one of it's parents is the watched element (i'm simply counting level for this). You may also have a boolean var, if the element is found or not, to not return the handler from inside the for clause. My example is limiting to that the handler only finishes, when nothing matches.
Adding cross-browser compatability, I'm usually doing it like this:
var addEvent = function (element, eventName, fn, useCapture) {
if (element.addEventListener) {
element.addEventListener(eventName, fn, useCapture);
}
else if (element.attachEvent) {
element.attachEvent(eventName, function (e) {
fn.apply(element, arguments);
}, useCapture);
}
};
This is cross-browser compatible code for attaching an event listener/handler, inclusive rewriting this in IE, to be the element, as like jQuery does for its event handlers. There are plenty of arguments to have some bits of jQuery in mind ;)
How about this:
jsBin demo
document.onclick = function(event){
var hasParent = false;
for(var node = event.target; node != document.body; node = node.parentNode)
{
if(node.id == 'div1'){
hasParent = true;
break;
}
}
if(hasParent)
alert('inside');
else
alert('outside');
}
you can use composePath() to check if the click happened outside or inside of a target div that may or may not have children:
const targetDiv = document.querySelector('#targetDiv')
document.addEventListener('click', (e) => {
const isClickedInsideDiv = e.composedPath().includes(targetDiv)
if (isClickedInsideDiv) {
console.log('clicked inside of div')
} else {
console.log('clicked outside of div')
}
})
I did a lot of research on it to find a better method. JavaScript method .contains go recursively in DOM to check whether it contains target or not. I used it in one of react project but when react DOM changes on set state, .contains method does not work. SO i came up with this solution
//Basic Html snippet
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="mydiv">
<h2>
click outside this div to test
</h2>
Check click outside
</div>
</body>
</html>
//Implementation in Vanilla javaScript
const node = document.getElementById('mydiv')
//minor css to make div more obvious
node.style.width = '300px'
node.style.height = '100px'
node.style.background = 'red'
let isCursorInside = false
//Attach mouseover event listener and update in variable
node.addEventListener('mouseover', function() {
isCursorInside = true
console.log('cursor inside')
})
/Attach mouseout event listener and update in variable
node.addEventListener('mouseout', function() {
isCursorInside = false
console.log('cursor outside')
})
document.addEventListener('click', function() {
//And if isCursorInside = false it means cursor is outside
if(!isCursorInside) {
alert('Outside div click detected')
}
})
WORKING DEMO jsfiddle
using the js Element.closest() method:
let popup = document.querySelector('.parent-element')
popup.addEventListener('click', (e) => {
if (!e.target.closest('.child-element')) {
// clicked outside
}
});
To hide element by click outside of it I usually apply such simple code:
var bodyTag = document.getElementsByTagName('body');
var element = document.getElementById('element');
function clickedOrNot(e) {
if (e.target !== element) {
// action in the case of click outside
bodyTag[0].removeEventListener('click', clickedOrNot, true);
}
}
bodyTag[0].addEventListener('click', clickedOrNot, true);
Another very simple and quick approach to this problem is to map the array of path into the event object returned by the listener. If the id or class name of your element matches one of those in the array, the click is inside your element.
(This solution can be useful if you don't want to get the element directly (e.g: document.getElementById('...'), for example in a reactjs/nextjs app, in ssr..).
Here is an example:
document.addEventListener('click', e => {
let clickedOutside = true;
e.path.forEach(item => {
if (!clickedOutside)
return;
if (item.className === 'your-element-class')
clickedOutside = false;
});
if (clickedOutside)
// Make an action if it's clicked outside..
});
I hope this answer will help you !
(Let me know if my solution is not a good solution or if you see something to improve.)
It looks like key-press can only be executed on a focus element? I don't fully buy into that, there has to be a way to execute a key-press event similar to a click event?
I have a view that works with one item at a time. I have a mouseenter - mouseleave function that adds a class to the item the mouse is over. When the item receives that class I want to be able to use a key-press event to run a function on that item.
Obviously this is a slight obstacle but Id like to find out what I need to do. Below is an example view.
var PlayerView = Backbone.View.extend({
tagName: 'div',
events: {
'click .points, .assists, span.rebounds, span.steals':'addStat',
'mouseenter': 'enter',
'mouseleave': 'leave',
'keypress': 'keyAction'
},
enter: function() {
this.$el.addClass('hover');
},
leave: function() {
this.$el.removeClass('hover');
},
keyAction: function(e) {
var code = e.keyCode || e.which;
if(code == 65) {
alert('add assist')
}
}
});
So there isn't much logic here, but I am thinking I would write something like this
keyAction: function(e) {
var code = e.keyCode || e.which;
if(code == 65) {
var addAssist = parseInt(this.model.get('assists')) + 1;
this.model.save({assists: addAssist});
}
}
Basically If I could figure out how to fire that keyAction method I should be good to go. So what are some caveats I am missing in executing some code like this? I am sure there are a few.
I do understand some of what is wrong with this code, it has no way of knowing when we run keypress in that view, I would have to add a conditional or something to find the active class, so when I execute the keypress it knows what model I am talking about, very vague description here but I get there is something wrong I am just not sure how to do this?
My solution
initialize: function() {
this.listenTo(this.model, "change", this.render);
_.bindAll(this, 'on_keypress');
$(document).bind('keydown', this.on_keypress);
},
enter: function(e) {
this.$el.addClass('hover');
},
leave: function(e) {
this.$el.removeClass('hover');
},
on_keypress: function(e) {
// A for assist
if(e.keyCode == 65) {
if(this.$el.hasClass('hover')) {
var addThis = parseInt(this.model.get('assists')) + 1;
this.model.save({assists: addThis});
}
}
// R for rebound
if(e.keyCode == 82) {
if(this.$el.hasClass('hover')) {
var addThis = parseInt(this.model.get('rebounds')) + 1;
this.model.save({rebounds: addThis});
}
}
// S for steal
if(e.keyCode == 83) {
if(this.$el.hasClass('hover')) {
var addThis = parseInt(this.model.get('steals')) + 1;
this.model.save({steals: addThis});
}
}
// 1 for one point
if(e.keyCode == 49) {
if(this.$el.hasClass('hover')) {
var addMake = parseInt(this.model.get('made_one')) + 1;
this.model.save({made_one: addMake});
var addOne = parseInt(this.model.get('points')) + 1;
this.model.save({points: addOne});
}
}
// 2 for two points
if(e.keyCode == 50) {
if(this.$el.hasClass('hover')) {
var addMake = parseInt(this.model.get('made_two')) + 1;
this.model.save({made_two: addMake});
var addTwo = parseInt(this.model.get('points')) + 2;
this.model.save({points: addTwo});
}
}
// 2 for two points
if(e.keyCode == 51) {
if(this.$el.hasClass('hover')) {
var addMake = parseInt(this.model.get('made_three')) + 1;
this.model.save({made_three: addMake});
var addThree = parseInt(this.model.get('points')) + 3;
this.model.save({points: addThree});
}
}
}
This is cool for my app because when the user hovers over the item the user can hit a key to add data, instead of clicking.
So you are only going to be able to listen to the keypress in whichever element that you have the listener set on (or its children). And the keypress event is only going to fire if the element is focused. So I think the best solution for you would be to set focus on the element you are hovering over, then you can listen for the keypress, or better yet, listen to keydown because it behaves in a more standard way cross browser.
Here is a working JSFiddle demonstrating this technique: http://jsfiddle.net/DfjF2/2/
Only certain form elements accept focus. You can add contenteditable or tabindex attributes to the element, and that should allow pretty much any element to receive focus, but then the keydown event won't actually get fired! This is a browser specific issue. In my experience, a <span> will cause keydown and keyup events to be fired in every browser I have tested (Chrome, Firefox, IE, Safari, Android browser, Silk). So in the jsfiddle I added a span inside the target element, put focus on that, and added the keydown event listener to it.
So if you added an empty <span> into your view, your code could look something like this:
var PlayerView = Backbone.View.extend({
tagName: 'div',
events: {
'click .points, .assists, span.rebounds, span.steals':'addStat',
'mouseenter': 'enter',
'mouseleave': 'leave',
'keydown': 'keyAction'
},
enter: function() {
this.$el.addClass('hover');
var span = this.$el.find('span');
span.attr('tabindex', '1').attr('contenteditable', 'true');
span.focus();
},
leave: function() {
this.$el.removeClass('hover');
var span = this.$el.find('span');
span.removeAttr('contenteditable').removeAttr('tabindex');
span.blur();
},
keyAction: function(e) {
var code = e.keyCode || e.which;
if(code == 65) {
alert('add assist')
}
}
});
I'm working on a project for my JavaScript class, and I don't know how to edit this jQuery where when you select a tab, it will bring you to a new page. I try adding "a href" to the body, but it doesn't look right. Is there a piece of code I have to enter in the jQuery so when you choose "About" that it will bring you to the actual page? Here's the code:
jQuery
function handleEvent(e) {
var el = $(e.target);
if (e.type == "mouseover" || e.type == "mouseout") {
if (el.hasClass("tabStrip-tab") && !el.hasClass("tabStrip-tab-click")) {
el.toggleClass("tabStrip-tab-hover");
}
}
if (e.type == "click") {
if (el.hasClass("tabStrip-tab-hover")) {
var id = e.target.id;
var num = id.substr(id.lastIndexOf("-") + 1);
if (currentNum != num) {
deactivateTab();
el.toggleClass("tabStrip-tab-hover")
.toggleClass("tabStrip-tab-click");
showDescription(num);
currentNum = num;
}
}
}
}
function deactivateTab() {
var descEl = $("#tabStrip-desc-" + currentNum);
if (descEl.length > 0) {
descEl.remove();
$("#tabStrip-tab-" + currentNum).toggleClass("tabStrip-tab-click");
}
}
$(document).bind("click mouseover mouseout", handleEvent);
HTML
<div class="tabStrip">
<div id="tabStrip-tab-1" class="tabStrip-tab">Home</div>
<div id="tabStrip-tab-2" class="tabStrip-tab">About</div>
<div id="tabStrip-tab-3" class="tabStrip-tab">Contact</div>
<div id="tabStrip-tab-3" class="tabStrip-tab">Gallery</div>
</div>
add this to your handler if you need a new page..
window.open('url', 'window name', 'window settings');
or this if you want to redirect the actual view
window.location.href('url');
furthermore this should be a better choice:
$('div[id^=tabStrip-tab]').bind("click mouseover mouseout", handleEvent);
now only the 'tabStrip-*' id´s will trigger the events/handler
The best solution for your problem is to put hidden div with content for every tab you have.
All you have to do is display the current div depending which tag is selected. The another solution is using ajax and then you have a template for the content and you fill the template with the data you have received.
Why does FramedCloud popup steal click events inside the popup?
current_popup = new OpenLayers.Popup.FramedCloud(
"featurePopup",
f.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(0,0),
"<b>Наблюдения</b><br/>" + $.map(features, function(fe) { return fe.attributes.description; }).join('<br/>'),
null, false, null);
map.addPopup(current_popup, true);
$('#map').on('click', function() { console.log('test'); return false; });
Captures click events always except when I click a link inside a popup. The popup and the anchors are descendants of #map.
Click the map => callback is fired
Click a marker => callback is fired, popup is shown
click inside popup (not on a link) => callback is not fired
click a link inside a popup => same way, nothing happens
The code in that part of OL is quite obscure.
Why does it catch clicks inside the popup? How do I take them back?
edit: debugging deeper in OL: this function is fired:
bindAsEventListener: function(func, object) {
return function(event) {
return func.call(object, event || window.event);
};
event.target is the anchor, exactly what I expect:
<a class="edit-card-link" href="/form/?id=806">...</a>
func is:
handleBrowserEvent: function(evt) {
var type = evt.type, listeners = this.listeners[type];
if (!listeners || listeners.length == 0) {
return;
}
var touches = evt.touches;
if (touches && touches[0]) {
var x = 0;
var y = 0;
var num = touches.length;
var touch;
for (var i = 0; i < num; ++i) {
touch = touches[i];
x += touch.clientX;
y += touch.clientY;
}
evt.clientX = x / num;
evt.clientY = y / num;
}
if (this.includeXY) {
evt.xy = this.getMousePosition(evt);
}
this.triggerEvent(type, evt);
}
this is OpenLayers.Event class instance, evt.target is still that anchor, listeners contains 1 listener:
function (evt){OpenLayers.Event.stop(evt,true);}
Is this the reason? How do I take it out?
If you want to stop the popup from stealing a mouse event then in your CSS you could, as suggested here, set the pointer-events: none; for the id corresponding to the popup id given at its creation. Thus in your case it would be:
#featurePopup{
pointer-events: none;
}
It worked like a charm for me when I wanted to avoid flickering of a popup which I showed on mouseover.
I did it another way. I let OpenLayers capture the event, but before that I trigger another one.
$('a', current_popup.contentDiv).on('click', function(evt) {
var jtarget = $(evt.target);
hide_popup(); // hides OpenLayers popup
$(document).trigger('edit_link_clicked', {
feature: features[jtarget.parent().find('a').index(jtarget)],
cluster: f,
url: jtarget.attr('href')
});
return false;
});