Some simple event driven code. For whatever reason, I can't seem to pass 'onchange' as a parameter to fireEvent(). Throws me an invalide argument error in ie 7/8. This project needs to be native. Little help?
Custom Event Creation:
createCustomEvent : function(eventName) {
var evt;
if(document.createEvent) {
evt = document.createEvent('CustomEvent');
evt.initEvent(eventName, true, true);
}else if(document.createEventObject) {
evt = document.createEventObject();
evt.eventName = eventName;
}
return evt;
},
dispatchCustomEvent : function (el, evt) {
if(el.dispatchEvent) {
el.dispatchEvent(evt);
}else if(el.fireEvent) {
console.log('on'+evt.eventName); //onchange
el.fireEvent('on'+evt.eventName, evt);
}
}
Usage:
dispatchCustomEvent(element, createCustomEvent('change'));
Okay, so according to most docs the change event will fire on any element and I quote:
"The change event is fired when an element loses focus and its value changed since gaining focus."
https://developer.mozilla.org/en-US/docs/DOM/Mozilla_Event_Reference/change
However, in <= ie8 onchange will not fire on any element besides form elements. This is incredibly lame imo, and makes modern MVC custom event listening and dispatching an issue.
Long story short, in my case I used the blur event to capture changes to my div element. This worked for me as the focus is removed between div element updates. It's a slideshow application, where two divs pop on and off the stack, left to right depending on the current location.
Related
I've created a fiddle to reproduce the problem.
https://jsfiddle.net/rvwp47Lz/23/
callback: function (key, option) {
console.log("You clicked the test button", this);
// Need the iframe contents to regain focus so the mouse events get caught
setTimeout(function () {
$iframe[0].contentWindow.focus();
}, 100);
}
Basically, what I want to happen is the mouse move events to be caught after closing the context menu.
I can call focus on the iFrame's body or document but it doesn't seem to have any effect.
After you right click one of the items within the iframe and select an item, the mousemove event on the iframes body is no longer called (you can also notice that the hover CSS effect on the items are no longer working).
Ideas?
After some debugging and playing around with jQuery.contextMenu's code it seems the issue actually comes from the itemClick function. I added comments to the code and will add an issue to their github for a possible fix (unless there's some reason they're disabling default here)
// contextMenu item click
itemClick: function (e) {
var $this = $(this),
data = $this.data(),
opt = data.contextMenu,
root = data.contextMenuRoot,
key = data.contextMenuKey,
callback;
// abort if the key is unknown or disabled or is a menu
if (!opt.items[key] || $this.is('.' + root.classNames.disabled + ', .context-menu-submenu, .context-menu-separator, .' + root.classNames.notSelectable)) {
return;
}
// This line is causing the issue since it's preventing the default actions which puts
// mouse events back into place. Chrome must disable mouse move events when the contextmenu event
// gets triggered to improve performance.
//e.preventDefault();
e.stopImmediatePropagation();
I want to fire an event in a textarea immediately after paste some text inside the textarea. I can do that when Shift+Ins is used; however, I cannot do it when right mouse button and then paste (from the drop down menu) is chosen. Keyup fires after Shift+Ins. None of the rest fires when Paste is chosen after right mouse button clicking... What do I have to do?
<textarea name="message" id="message"></textarea>
$("#message").on('keyup contextmenu', function(event) {
alert("ok");
});
http://jsfiddle.net/f29vuwoL/7/
Thank you
Most browsers support the input event, which is fired when something is pasted or otherwise added, regardless of how:
$("#message").on('keyup contextmenu input', function(event) {
alert("ok");
});
Updated Fiddle
Note that using input is the most general method, firing when the control gets input regardless of how, and so if you hook multiple events (as above), you'll get multiple calls for the same input. For instance, if you hook both keyup and input, on browsers that support input, you'll get two calls. Similarly for paste and input when the user pastes, on browsers that support both.
If you need to support browsers that don't have either input or paste, I'm afraid the unfortunate answer is that you need to poll. Still, polling every (say) 250ms isn't asking the browser to do that much work, and you can feature-detect whether it's necessary:
var message = $("#message");
var events = null;
var previous;
if ('oninput' in message[0]) {
// Browser supports input event
events = "input";
} else if ('onpaste' in message[0]) {
// Browser supports paste event
events = "paste keyup contextmenu";
}
if (!events) {
// Ugh, poll and fire our own
events = "pseudoinput";
previous = message.val();
setInterval(function() {
var current = message.val();
if (current != previous) {
previous = current;
message.trigger(events);
}
}, 250);
}
console.log("Using: " + events);
message.on(events, function(e) {
console.log("Got event: " + e.type);
});
Updated Fiddle
You should use input event callback. See the demo here
You can use the dedicated paste event:
$("#message").on('paste', function(event) {
alert("ok");
});
Updated jsFiddle
However you might want to check browser support - I don't think jQuery normalizes this event.
If you need IE support, it might be a little more difficult, but it depends on your requirements - does it absolutely need to be a paste action? If not, TJ Crowder's answer is the way to go.
The on input is useful if you want to detect when the contents of a textarea, input:text, input:password or input:search element have changed, because the onchange event on these elements fires when the element loses focus, not immediately after the modification.The oninput event is supported in Internet Explorer from version 9.
$("#message").on('input propertychange', function() {
console.log($(this).val());
});
Fiddle
I have a dropdown for number of travelers.
When I change the value (say select 2), it displays some more dropdowns (in this case 2 dropdowns) for entering the age of travelers.
This is existing functionality. Now I have created another dropdown, here I have written an onChange function that sets the value of travelers:
document.getElementById("travellers").value="1";
I want the additional dropdowns for the age to appear on their own which does not happen.
How can I effect this to happen using jQuery/JavaScript?
When you modifies value programatically event will not fire. You need to trigger event.
Using vanilla JS
var select = document.getElementById("travellers");
//fire the event
if("createEvent" in document) { //NON IE browsers
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
select.dispatchEvent(evt);
} else { //IE
var evt = document.createEventObject();
select.fireEvent("onchange", evt);
}
As you have tagged your question with jQuery you can use .trigger()
$("#travellers").trigger("change");
I'm trying to use JavaScript events to check an input checkbox in JSDOM.
<input type="checkbox" id="foo" />
But I can't seem to get it to check itself by dispatching an event on it:
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, true);
document.querySelector('#foo').dispatchEvent(evt)
However, it does work when I use jQuery's .trigger('click')
Why doesn't this code work in jsdom? I feel there's some minor inconsistency in jsdom and likely some other browser which jQuery fixes.
There is a browser dependency on the way you can manually trigger events in JavaScript.
Here's a demo.
The Code:
document.getElementById("foo").value='500';
if (document.getElementById("foo").fireEvent) {
document.getElementById("foo").fireEvent("onclick");
} else if (document.getElementById("foo").dispatchEvent) {
var clickevent=document.createEvent("MouseEvents");
clickevent.initEvent("click", true, true);
document.getElementById("foo").dispatchEvent(clickevent);
}
Updated Fiddle
Updated Code:
if (document.getElementById("foo").fireEvent) {
document.getElementById('car-make').attachEvent('onchange', update);
document.getElementById("foo").fireEvent("onchange");
} else if (document.getElementById("foo").dispatchEvent) {
document.getElementById('foo').addEventListener('change', update, false);
var clickevent=document.createEvent("MouseEvents");
clickevent.initEvent("change", true, true);
document.getElementById("foo").dispatchEvent(clickevent);
}
function update () {
alert('changed');
}
From the specs:
The change event occurs when a control loses the input focus and its value has been modified since gaining focus. This event is valid for INPUT, SELECT, and TEXTAREA. element.
Bubbles: Yes
Cancelable: No
Context Info: None
Note how this is different from the click event, for example:
The click event occurs when the pointing device button is clicked over an element.
Thus, triggering a change event will not actually change the input value.
Loosely speaking, the Cancelable: No property says that nothing will happen by default.
I have a clearable input like this:
+-----------------+
| x |
+-----------------+
The clear icon is a span with a font glyph in the :before:
<wrapper>
<input>
<icon span>
</wrapper>
Validation of inputs is done on blur (which re-renders the input View for validation message and icon changes - this keeps the architecture simple). The issue I am experiencing is that by clicking the icon the input triggers a blur and then the icon click.
Can you think of a way to either:
a) Avoid triggering a blur -- I can only think of ditching font glyph and using a background image, but I am already using other glyphs for required, invalid etc in that position so it is undesired
b) Detecting that the blur was caused by the icon and not something else
Thanks.
Edit: Here is one idea, a bit lame using a setTimeout though: http://jsfiddle.net/ferahl/td5VR/
Consider using mousedown and mouseup events to set/remove a flag.
http://jsfiddle.net/td5VR/4/
var wasClicked = false;
$('input').blur(function(){
$(".results").text(wasClicked ? "was clicked": "wasn't clicked");
});
$('.something').mousedown(function(){
wasClicked = true;
}).mouseup(function() {
wasClicked = false;
});
Though you still need to disable keyboard navigation to the link by setting tabindex="-1".
Here's a few ideas of what might be happening and some approaches to try:
This is a guess, but perhaps what you're experiencing is something called event bubbling. Take a look at this page to learn more about it. You can prevent event bubbling in your click handler like this:
IconElement.onclick = function(event) {
event = event || window.event // cross-browser event
if (event.stopPropagation) {
// W3C standard variant
event.stopPropagation()
} else {
// IE variant
event.cancelBubble = true
}
}
(If you're using jQuery, you don't need to worry about the "IE variant")
You could also try adding return false; or event.preventDefault() and see if that works.
And one more approach is to check event.target in your blur handler:
InputElement.onblur = function(event) {
event = event || window.event // cross-browser event
var IconElement = [do something to get the element];
if (event.target == IconElement) {
// Ignore this blur event, or maybe even call "this.focus()"
}
}
Here is the final very simple solution inspired by #Yury's answer:
$('.clearable-icon').mousedown(function() {
// This happens before blur, so return false and stop propagation.
return false;
});