Javascript click function - javascript

I've got some code which works fine in IE but unfortunately not in Google Chrome/Firefox.
It relies upon calling a click() event on a button from javascript. Reading around it seems that this is an IE specific extension (doh). Is there any way I can do a similar thing in chrome + firefox? To clarify, it's executing the click event on a specific button, not handling what happens when the user clicks on a button.
Thanks
The code for those who asked for it:
function getLinkButton(actionsDiv)
{
var hrefs = actionsDiv.getElementsByTagName("a");
for (var i=0; i<hrefs.length; i++)
{
var id = hrefs[i].id;
if (id !=null && id.endsWith("ShowSimilarLinkButton"))
{
return hrefs[i];
}
}
return null;
}
function doStuff()
{
//find the specific actions div... not important code...
var actionsDiv = getActionsDiv();
var linkButton = getLinkButton(actionsDiv);
if (linkButton != null)
{
if (linkButton.click)
{
linkButton.click();
}
else
{
alert("Cannot click");
}
}
}
I don't really want to use jQuery unless absolutely necessary

I think you're looking for element.dispatchEvent:
function simulateClick() {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var cb = document.getElementById("checkbox");
var canceled = !cb.dispatchEvent(evt);
if(canceled) {
// A handler called preventDefault
alert("canceled");
} else {
// None of the handlers called preventDefault
alert("not canceled");
}
}
I read your question as "I'm trying to fire the onclick event for my button", whereas everyone else seems to have read it as "I'm trying to handle an onclick event for my button". Please let me know if I've got this wrong.
Modifying your code, a proper x-browser implementation might be:
if (linkButton != null)
{
if (linkButton.fireEvent)
linkButton.fireEvent("onclick");
else
{
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
linkButton.dispatchEvent(evt);
}
}

onclick attribute should be crossbrowser:
<input type="button" onclick="something()" value="" />
EDIT
And there was this question that seems to be about the same problem: setAttribute, onClick and cross browser compatibility

onclick="methodcall();" works for me fine...

you can use onClick attribute or if you need more functionality have a look at jQuery and events it offers: http://api.jquery.com/category/events/

Related

Simulating drag and drop on a SortableJS sortable list using JavaScript

I'm attempting to simulate a drag and drop action on a sortable HTML list created using the Sortable library. It uses the native HTML5 API to implement draggable elements and sorting within a list.
To simulate these drag events, I found and modified the following JavaScript code:
var triggerSortableDragAndDrop = function (selectorDrag, selectorDrop, callback) {
var DELAY_INTERVAL_MS = 10;
var MAX_TRIES = 2;
// fetch target elements
var elemDrag = document.querySelector(selectorDrag);
var elemDrop = document.querySelector(selectorDrop);
elemDrag.setAttribute('draggable',"true");
elemDrop.setAttribute('draggable',"true");
elemDrag.href="#";
var dragItems = document.querySelectorAll('[draggable=true]');
if (!elemDrag || !elemDrop) {
console.log("can't get elements");
return false;
}
var startingDropRect = elemDrop.getBoundingClientRect();
function rectsEqual(r1, r2) {
return r1.top === r2.top && r1.right === r2.right && r1.bottom === r2.bottom && r1.left === r2.left;
}
// function for triggering mouse events
function fireMouseEvent(type, elem) {
var evt = document.createEvent('MouseEvent');
evt.initMouseEvent(type, true, true, window, 1, 1, 1, 0, 0, false, false, false, false, 0, elem);
elem.dispatchEvent(evt);
};
// trigger dragging process on top of drop target
// We sometimes need to do this multiple times due to the vagaries of
// how Sortable manages the list re-arrangement
var counter = 0;
function dragover() {
counter++;
console.log('DRAGOVER #' + counter);
var currentDropRect = elemDrop.getBoundingClientRect();
if (rectsEqual(startingDropRect, currentDropRect) && counter < MAX_TRIES) {
if (counter != 1) console.log("drop target rect hasn't changed, trying again");
// mouseover / mouseout etc events not necessary
// dragenter / dragleave events not necessary either
fireMouseEvent('dragover', elemDrop);
setTimeout(dragover, DELAY_INTERVAL_MS);
} else {
if (rectsEqual(startingDropRect, currentDropRect)) {
console.log("wasn't able to budge drop target after " + MAX_TRIES + " tries, aborting");
fireMouseEvent('drop', elemDrop);
if (callback) callback(false);
} else {
setTimeout(drop, DELAY_INTERVAL_MS);
}
}
}
function drop() {
console.log('DROP');
// release dragged element on top of drop target
fireMouseEvent('drop', elemDrop);
fireMouseEvent('mouseup', elemDrop); // not strictly necessary but I like the symmetry
if (callback) callback(true);
}
// start dragging process
console.log('DRAGSTART');
fireMouseEvent('mousedown', elemDrag);
console.log('mousedown triggered');
fireMouseEvent('dragstart', elemDrag);
console.log('dragstart triggered');
// after a delay, do the first dragover; this will run up to MAX_TRIES times
// (with a delay between each run) and finally run drop() with a delay:
setTimeout(dragover, DELAY_INTERVAL_MS);
return true;
};
And the markup of the section I'm trying to drag and drop with is as follows:
When I tried to set breakpoints on the browser's drag event listeners, and execute the helper function in my browser console using:
triggerSortableDragAndDrop('#bookmarkItems > li:nth-child(2)', '#bookmarkItems > li:nth-child(2)');
I noticed that the dragstart event was never captured, but the mousedown and dragover events were.
How can I get the dragstart event fire to trigger its listener? Because I think that is what's causing the drag and drop simulation to fail.
I can see in your code the dragstart event is created of type MouseEvent while it is of type DragEvent.
var elem = document.getElementById("one");
var mousedown = document.createEvent('MouseEvent');
mousedown.initMouseEvent("mousedown", true, true, window, 1, 1, 1, 0, 0, false, false, false, false, 0, elem);
elem.dispatchEvent(mousedown);
var dragstart = document.createEvent('DragEvent');
dragstart.initMouseEvent("dragstart", true, true, window, 1, 1, 1, 0, 0, false, false, false, false, 0, elem);
elem.dispatchEvent(dragstart);
<div id="one" draggable="true" onmousedown="console.log('mousedown')" ondragstart="console.log('dragstart')">drag me</div>
Creating the dragstart as an event of the correct type, at least on Chrome and Edge, it works.
Hope this helps.
I used a more modern approach to trigger the dragstart and mousedown events (note that using event constructors is preferable over document.createEvent()). Both events work as expected. Some code to illustrate that below:
let text = document.getElementById('image');
text.addEventListener('dragstart', () => {
console.log('dragstart triggered')
});
text.addEventListener('mousedown', () => {
console.log('mousedown triggered')
});
function btn_click() {
const evt_1 = new MouseEvent('mousedown');
text.dispatchEvent(evt_1);
const evt_2 = new DragEvent('dragstart');
text.dispatchEvent(evt_2);
}
<p>Drag around the image to trigger the ondragstart and mousedown event.</p>
<button onclick='btn_click()'>Programatically trigger the ondragstart and onmousedown events.</button>
<br>
<br>
<img id='image' src='https://via.placeholder.com/150'>
However there is a big unknown in your code; How does the library you are using handle these events? Does it even handle the ondragstart event? It may very well only use other events, thus you can't assume these events in your JS code. The main issue is the coupling between your JS and that in the library.
So there are 2 ways to go about this
Ensure your code uses the events the library responds to (keep in mind that the code in the library and the available events may change over time)
Implement your own drag-and-drop behaviour
PS: If you are writing tests, you may decide not to test the library and trust it to behave as expected. Maybe you can validate whether your implementation of the library is correct instead.

JavaScript onfocus attribute and key events

I am trying to simulate an keyinput in JavaScript on a textbox, in Firefox. The textbox has an onfocus=" this.value='' " attribute. A simulation + my code can be found at
Working code:
var divy = document.getElementById("eventListener");
divy.focus();
var inputText = '';
for(var i = 0; i < ('asd').length; i++)
{
var event = document.createEvent('KeyboardEvent');
event.initKeyEvent ('keydown', true, true, null, false, false, false, false, 0, 0)
divy.dispatchEvent(event);
inputText += ('asd').charAt(i);
var event = document.createEvent('KeyboardEvent');
event.initKeyEvent ('keypress', true, true, null, false, false, false, false, 0, ('asd').charCodeAt(i))
divy.dispatchEvent(event);
divy.value = inputText;
var event = document.createEvent('KeyboardEvent');
event.initKeyEvent ('keyup', true, true, null, false, false, false, false, 0, 0)
divy.dispatchEvent(event);
}
divy.blur();
My question is, how to properly simulate the input (without jquery!) so that the second textbox doesn't have an empty value. And also as the focus event is only once thrown, why gets the value erased each time.
UPDATE:
As I thought that the divy.focus(); Method might need some time to execute the onfocus event in attributes, I set up a timeout to send the key events, using:
windows.setTimeout("fireKeys2()", 5000);
But this also does not seem to work. The test is located here
http://jsfiddle.net/hPBNA/23/
UPDATE 2:
I figured out the problem myself, it seems like if element.value has been set to '' this way (element.value = '') element.setAttribute('value', someText) is not able to change it. Accessing the element.value property instead gave me the right results.
Tested in Firefox 22. Don't know if its reproducible on other versions.
I figured out the problem myself, it seems like if element.value has been set to '' this way (element.value = ''), element.setAttribute('value', someText) is not able to change it. Accessing the element.value property instead gave me the right results.
Tested in Firefox 22. Don't know if its reproducible on other versions.
John

Fire event in Raphael.js

I have an Raphael element with click event handler:
var paper = Raphael("container", 770, 160);
var c = paper.rect(10, 10, 50, 50);
c.click(function () {
alert("triggering");
})
How I can manually fire this event? (c.click() don't work)
Thanks!
Although this question is already answered, I will post my solution which I found out by random.
It's possible with the Raphael internals:
When you attach an event listener like element.click(func) then the element object holds an array with all events. In this array there's an object which has a method f (strange naming convention) which triggers the event.
So to sum it up you can call your event with knowing the order of your events, in your case there's just the click event which is on index 0, you can call it like: c.events[0].f();
A more generic solution would be a function like
function triggerClick(element) {
for(var i = 0, len = element.events.length; i < len; i++) {
if (element.events[i].name == 'click') {
element.events[i].f();
}
}
}​
But beware that if you had multiple click events all were triggered.
Here's a fiddle to demonstrate.
Even though this has already been answered a while ago, I was looking for something a little "more native" in nature. Here's how I go about it without relying on Mootools or jQuery.
var evObj = document.createEvent('MouseEvents');
evObj.initEvent('click', true, false);
c.node.dispatchEvent(evObj);
This basically creates the event in the browser and then dispatches it to the node associated with the Raphaël object.
Here's also the MOZ link for reference:
https://developer.mozilla.org/en-US/docs/DOM/document.createEvent
I actually found a slightly more elegant way to use Kris' method.
Raphael supports native extension of the element object so I built a little patch to add the trigger method to raphael
here it is:
//raphael programatic event firing
Raphael.el.trigger = function (str, scope, params){ //takes the name of the event to fire and the scope to fire it with
scope = scope || this;
for(var i = 0; i < this.events.length; i++){
if(this.events[i].name === str){
this.events[i].f.call(scope, params);
}
}
};
I set up a Js fiddle to show how it works: here
EDIT :
The solution purposed by Dan Lee is working better.
I write a plug-in for this, use event to calculate the right position;
Raphael.el.trigger = function(evtName, event) {
var el = this[0]; //get pure elements;
if (event.initMouseEvent) { // all browsers except IE before version 9
var mousedownEvent = document.createEvent ("MouseEvent");
mousedownEvent.initMouseEvent (
"mousedown", true, true, window, 0,
event.screenX, event.screenY, event.clientX, event.clientY,
event.ctrlKey, event.altKey, event.shiftKey, event.metaKey,
0, null);
el.dispatchEvent (mousedownEvent);
} else {
if (document.createEventObject) { // IE before version 9
var mousedownEvent = document.createEventObject (window.event);
mousedownEvent.button = 1; // left button is down
el.fireEvent (evtName, mousedownEvent);
}
}
};
Usage:
circle2.mousedown(function(e) {
var circle = this.clone();
circle.drag(move, down, up);
circle.trigger("mousedown", e);
});

Simulate Textbox Click to get focus

I am trying the following code to fire click event on a textbox while clicking on a button as the focus() function is not working in IE8
function simulateClick(elm) {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var canceled = !elm.dispatchEvent(evt);
if(canceled) {
// A handler called preventDefault
// uh-oh, did some XSS hack your site?
} else {
// None of the handlers called preventDefault
// do stuff
}
}
This code works fine if the element is of type checkbox but not textbox, is there anything I might need to add?
This is the code for focus
function ResponseEnd(sender, args) {
if (args.get_eventArgument().indexOf("Filter") != -1) {
var grid = document.getElementById("<%= radGridEnquiries.ClientID %>");
var label = $(grid).children("table").children("tbody").children(".rgRow").children("td:has(span)").children("span")[0];
if (label != null) {
label.focus();
}
else {
var noRecTemp = $(grid).children("table").children("tbody").children("tr.rgNoRecords").children("td:has(div)").children("div");
noRecTemp.focus();
}
}
if (postInProgress)
postInProgress = false;
}
The real scenario is I have some textboxes set as filters in a Telerik RadGrid and having no filter icons but when the user posts a filter and the request is finished in IE8 the filter textbox is still with focus preventing the user to input new filters unless clicks on the textbox manually again
P.S. Sorry if this post is seen as answer but couldn't update this question with proper indented code. Thanks

How do I programmatically click on an element in JavaScript?

In IE, I can just call element.click() from JavaScript - how do I accomplish the same task in Firefox? Ideally I'd like to have some JavaScript that would work equally well cross-browser, but if necessary I'll have different per-browser JavaScript for this.
The document.createEvent documentation says that "The createEvent method is deprecated. Use event constructors instead."
So you should use this method instead:
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
and fire it on an element like this:
element.dispatchEvent(clickEvent);
as shown here.
For firefox links appear to be "special". The only way I was able to get this working was to use the createEvent described here on MDN and call the initMouseEvent function. Even that didn't work completely, I had to manually tell the browser to open a link...
var theEvent = document.createEvent("MouseEvent");
theEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
var element = document.getElementById('link');
element.dispatchEvent(theEvent);
while (element)
{
if (element.tagName == "A" && element.href != "")
{
if (element.target == "_blank") { window.open(element.href, element.target); }
else { document.location = element.href; }
element = null;
}
else
{
element = element.parentElement;
}
}
Using jQuery you can do exactly the same thing, for example:
$("a").click();
Which will "click" all anchors on the page.
element.click() is a standard method outlined by the W3C DOM specification. Mozilla's Gecko/Firefox follows the standard and only allows this method to be called on INPUT elements.
Are you trying to actually follow the link or trigger the onclick? You can trigger an onclick with something like this:
var link = document.getElementById(linkId);
link.onclick.call(link);
Here's a cross browser working function (usable for other than click handlers too):
function eventFire(el, etype){
if (el.fireEvent) {
el.fireEvent('on' + etype);
} else {
var evObj = document.createEvent('Events');
evObj.initEvent(etype, true, false);
el.dispatchEvent(evObj);
}
}
I used KooiInc's function listed above but I had to use two different input types one 'button' for IE and one 'submit' for FireFox. I am not exactly sure why but it works.
// HTML
<input type="button" id="btnEmailHidden" style="display:none" />
<input type="submit" id="btnEmailHidden2" style="display:none" />
// in JavaScript
var hiddenBtn = document.getElementById("btnEmailHidden");
if (hiddenBtn.fireEvent) {
hiddenBtn.fireEvent('onclick');
hiddenBtn[eType]();
}
else {
// dispatch for firefox + others
var evObj = document.createEvent('MouseEvent');
evObj.initEvent(eType, true, true);
var hiddenBtn2 = document.getElementById("btnEmailHidden2");
hiddenBtn2.dispatchEvent(evObj);
}
I have search and tried many suggestions but this is what ended up working. If I had some more time I would have liked to investigate why submit works with FF and button with IE but that would be a luxury right now so on to the next problem.

Categories