Use Event Handler Instead of onClick to Fire API Function - javascript

I have a simple checkbox.
<div class="myCheckBox"><label><input type="checkbox" checked><span class="label-text">My Label</span></label></div>
Note: The HTML is part of a stack that already has a unique ID assigned to it (referenced the the JS as %id%.
I want to connect it to a javascript function. I know I can use onClick in the HTML to achieve this, but in this use case I need an event handler in my javascript to call (correct term?) the function.
My JS is
$(document).ready(function() {
var stack = $('%id%'),
checkbox = $('.myCheckbox',stack);
function filterCheck(%id=filterName%, %id=values%) {
var sheet = mainViz.getWorkbook().getActiveSheet();
var updateType;
if(checkbox.is(":checked")) {
updateType = "ADD";
} else {
updateType = "REMOVE";
}
worksheetArray = sheet.getWorksheets();
for (var i = 0; i < worksheetArray.length; i++) {
worksheetArray[i].applyFilterAsync(filterName, values, updateType);
}
}
}
checkbox.click(function(e) {
}
});
The event handler (I assume) goes after the checkbox.click(function(e) { ...but I am at a moment of clueless loss. Help?

I could see one issue with the code.
var stack = $('%id%'),
checkbox = $('.myCheckbox',stack);
You are not using # to reference id of element. Correct way should be either escaping the special characters
var stack = $('#\\%id\\%')
or by wrapping up dom object with jQuery Wrapper
var stack = $(document.getElementById('%id%'))
Both will help to find the stack which you have used as context below
$('.myCheckbox',stack);
event handler should work fine as given.

Related

Event target should be anchor but is image instead

I am working on a dialog script in Vanilla JS. I ran into a problem with the click event on the video image. Even tough the image is surrounded with an anchor tag it shows the image as the event.target on the "trigger-dialog-open" event.
Here is the HMTL:
<a class="trigger-dialog--open thumbnail" data-dialog-id="dialog-video" href="javascript:;">
<figure>
<img src="http://i.ytimg.com/vi/id/sddefault.jpg" alt="" />
</figure>
</a>
And this is the event in JS:
var openTriggers = document.getElementsByClassName('trigger-dialog--open');
for (var i = 0; i < openTriggers.length; i++) {
openTriggers[i].addEventListener("click", function (event) {
this.openDialog(event.target.getAttribute('data-dialog-id'));
}.bind(this), false);
}
The event handler wants to know the dialog-id from the anchors data attribute. It can't be found because it thinks the image is the event.target, not the actual anchor. How can I correct this? Thanks!
Use event.currentTarget. The event.target is supposed to be the img element since that is what the user has clicked on. The click then bubbles up through the image's containers. event.currentTarget gives you the element that the click handler was actually bound to.
(Or if you didn't bind this to some other object you could use this within the click handler and it should also be the current target.)
I have a few questions is the var openTriggers supposed to be a part of a module hash? Because if it's global then you don't use a this, you only add a this, if it's referencing a variable that the function is also contained in. For example:
var aThing = {
openTriggers: document.getElementsByClassName('trigger-dialog--open'),
openModal: null,
openDialog: function(clickedThingAttr){
if(this.openModal !== null){
this.openModal.style.display = 'none';
}else{
this.openModal = document.getElementById(clickedThingAttr);
}
this.openModal = document.getElementById(clickedThingAttr);
this.openModal.style.display = 'block';
},
setEventListenersNStuff: function(){
for (var i = 0, n = this.openTriggers.length;i < n; i++) {
this.openTriggers[i].addEventListener("click", function (event) {
this.openDialog(event.target.getAttribute('data-dialog-id'));
});
};
}
};//end of aThing hash object
aThing.setEventListenersNStuff();
There are a few issues here:
1. why are you using .bind I think that is a jQuery thing, you want to pass a string to another function when an object is clicked, there no need for binding at all.
2. Also make sure that if you want to do something like open a modal, there is no need to call another method unless it's kinda complex.
3. What about other potential dialogs, it seems that when a .trigger-dialog--open is clicked you're just showing that one one modal with the embedded id, but what about others? Make sure all modals are closed before you open a new one, unless you want to have like 10 modals are open.
A thing to note: I added the line var i = 0, n = openTriggers.length;i < n; i++, now in this case it's silly optimization, and I heard for modern browsers this doesn't apply, but to explain why I added it, is because i < openTriggers.length would count and integrate the array N times. (This may be an outdated optmiziation).
If you meant global
Below I added a different set of code, just in case you meant that var openTriggers is global, kinda like you wrote above. Also I used querySelectorAll for this which is like jQuery's $('.thing') selector.
anyhoo, I also added
var openTriggers = document.querySelectorAll('.trigger-dialog--open');
var n = openTriggers.length;
function openDialog(ddId){
for (var i = 0;i < n; i++) {
openTriggers[i].style.display = 'none';
};
document.getElementById(ddId).style.display = 'block';
};
for (var i = 0;i < n; i++) {
openTriggers[i].addEventListener("click", function (event) {
openDialog(event.target.getAttribute('data-dialog-id'));
});
}
}
So for the question of hiding already open modals I would suggest you could either cache the open Dialog within a module, or you could toggle a class, which would be less efficient since it would require an extra DOM search. Additionally you could add a if this.openModal.id === clickedThingAttr to hide if open, that way you got a toggle feature.
Anyways I suggest you read up on this stuff, if you want to use plain JS but would like the features of jQuery: http://blog.romanliutikov.com/post/63383858003/how-to-forget-about-jquery-and-start-using-native
Thank you for your time.
You can use a closure
var openTriggers = document.getElementsByClassName('trigger-dialog--open');
for (var i = 0; i < this.openTriggers.length; i++) {
(function(element) {
element.addEventListener("click", function (event) {
element.openDialog(event.target.getAttribute('data-dialog-id'));
}, false)
})(openTriggers[i]);
}

Why does this window.addEventListener fire first, before doc.ready? [duplicate]

This question already has answers here:
Javascript "addEventListener" Event Fires on Page Load [duplicate]
(2 answers)
Closed 6 years ago.
I was experimenting [in jsfiddle] w/a function created to append a newly created TextNode to the <p> in the HTML below:
<button onclick="addTextNode('YES! ');">YES!</button>
<button onclick="addTextNode('NO! ');">NO!</button>
<button onclick="addTextNode('WE CAN! ');">WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
Here is my javascript as well:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
This works fine. However, the crux reveals itself when I attempt to make my javascript 'unobtrusive' by removing the behavior from the markup...
<button>YES!</button>
<button>NO!</button>
<button>WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
then utilizing a loop to attach addEventListener to each <button> element, which in turn uses the child TextNode to call addTextNode:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode(button.innerHTML));
}
Two strange things happen with my code:
When [jsfiddle's] Code Wrap is set to 'no wrap - in head', nothing happens.
However, When Code Wrap is set to 'onLoad', 'onDomReady' or 'no wrap - in body' the function runs before the click and I get this.
Could someone tell me what I'm missing?
The root of your problem is here:
button.addEventListener("click", addTextNode(button.innerHTML))
You're executing the function rather than passing it to the event listener. Instead, pass the function by reference, then get the innerHTML inside the function.
function addTextNode() {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode);
}
http://jsfiddle.net/bn85J/
First, your usage of Add Event listener is wrong. add event listener is expecting a function reference in the second parameter not a function call.
The following is a function reference:
var myfunctionreference = addTextNode;
This is a function call and will execute the function
var myfunctioncall = addTextNode();
In your code you are actually calling the function to use as the event handler instead of referencing it.
Here is some Reference for .addEventListener()
You should be binding the event like this:
button.addEventListener("click", addTextNode);
Second, the event knows the element and knows the event. Your function call should be created to accept the event and not an arbitrary string. Then utilizing the event or "this" will allow you to get your hands on the text your looking for.
function addTextNode(evt) {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}

Why does addEventListener fire before the event if at all? [duplicate]

This question already has answers here:
Javascript "addEventListener" Event Fires on Page Load [duplicate]
(2 answers)
Closed 6 years ago.
I was experimenting [in jsfiddle] w/a function created to append a newly created TextNode to the <p> in the HTML below:
<button onclick="addTextNode('YES! ');">YES!</button>
<button onclick="addTextNode('NO! ');">NO!</button>
<button onclick="addTextNode('WE CAN! ');">WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
Here is my javascript as well:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
This works fine. However, the crux reveals itself when I attempt to make my javascript 'unobtrusive' by removing the behavior from the markup...
<button>YES!</button>
<button>NO!</button>
<button>WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
then utilizing a loop to attach addEventListener to each <button> element, which in turn uses the child TextNode to call addTextNode:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode(button.innerHTML));
}
Two strange things happen with my code:
When [jsfiddle's] Code Wrap is set to 'no wrap - in head', nothing happens.
However, When Code Wrap is set to 'onLoad', 'onDomReady' or 'no wrap - in body' the function runs before the click and I get this.
Could someone tell me what I'm missing?
The root of your problem is here:
button.addEventListener("click", addTextNode(button.innerHTML))
You're executing the function rather than passing it to the event listener. Instead, pass the function by reference, then get the innerHTML inside the function.
function addTextNode() {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode);
}
http://jsfiddle.net/bn85J/
First, your usage of Add Event listener is wrong. add event listener is expecting a function reference in the second parameter not a function call.
The following is a function reference:
var myfunctionreference = addTextNode;
This is a function call and will execute the function
var myfunctioncall = addTextNode();
In your code you are actually calling the function to use as the event handler instead of referencing it.
Here is some Reference for .addEventListener()
You should be binding the event like this:
button.addEventListener("click", addTextNode);
Second, the event knows the element and knows the event. Your function call should be created to accept the event and not an arbitrary string. Then utilizing the event or "this" will allow you to get your hands on the text your looking for.
function addTextNode(evt) {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}

specific function in Javascript

I have a function took on a tutorial, it works fine with one only element but I want to use it with some elements and I do not know enough about Javascript to do so.
This is my function :
var elements = document.getElementsByClassName('boules');
for (var i = 0; i < elements.length; i++) {
gameAccel(elements[i]);
}
function gameAccel(sphere) {
var x=20,y=300,vx=0,vy=0,ax=0,ay=0;
if(window.DeviceMotionEvent!=undefined){
window.ondevicemotion=function(e){
ax=event.accelerationIncludingGravity.x*3;
ay=event.accelerationIncludingGravity.y*3;
}
monInterval = setInterval(function(){
var landscapeOrientation=window.innerWidth/window.innerHeight>1;
if(landscapeOrientation){
vx=vx+ay;
vy=vy+ax;
}else{
vy=vy-ay;
vx=vx+ax;
}
vx=vx*0.98;
vy=vy*0.98;
y=parseInt(y+vy/50);
x=parseInt(x+vx/50);
boundingBoxCheck();
sphere.style.top=y+"px";
sphere.style.left=x+"px";
},25);
}
function boundingBoxCheck(){
if(x<0){x=0;vx=-vx;}
if(y<0){y=0;vy=-vy;}
if(x>document.documentElement.clientWidth-40){
x=document.documentElement.clientWidth-40;
vx=-vx;
}
if(y>document.documentElement.clientHeight-40){
y=document.documentElement.clientHeight-40;
vy=-vy;
}
}
}
I have one element with "boules" class, it works, if I have several elements with "boules" class it doesn't works.
This function is used on mobile device with gyroscope. (this is the basic example http://www.albertosarullo.com/demos/accelerometer/).
Someone can explain me why and how I can correct that ?
Thanks a lot.
You are overwriting window.ondevicemotion and monInterval every time you call the function. Only the last handler will be triggered. Instead, use addEventListener to attach multiple handlers and a local variable.
You have overwrites window.ondevicemotion handler in every loop. It must works only for last handler.

Javascript Onclick vs Onmousedown Race Condition

I have a SUBMIT and SAVE button for a form that are by default listening for Onclick events.
When the form is SUBMITTED OR SAVED - the page resets the scroll position to the TOP of the page.
Recently the users of the applications have requested that the page stay at the bottom of the page where the buttons are located for only a subset of forms.
(These buttons are used across hundreds of other forms so I cannot change the reset of the scrolling globally.)
So the solution that I am trying to implement involves a couple hidden input fields and a few event listeners.
I have added an onmousedown event for these buttons, like so -
// Submit and Save button listeners
var globalButtons;
if (v_doc.getElementsByClassName) {
globalButtons = v_doc.getElementsByClassName('globalbuttons');
}
// Internet Explorer does not support getElementsByClassName - therefore implement our own version of it here
else {
globalButtons = [];
var myclass = new RegExp('\\b'+'globalbuttons'+'\\b');
var elem = v_doc.body.getElementsByTagName("input");
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) {
globalButtons.push(elem[i]);
}
}
}
for (var gb = 0; gb < globalButtons.length; gb++) {
if (globalButtons[gb].name == 'methodToCall.route' ||
globalButtons[gb].name == 'methodToCall.save') {
if(globalButtons[gb].addEventListener) { //all browsers except IE before version 9
globalButtons[gb].addEventListener("mousedown", function(){flagSpecialScrollOnRefresh()},false);
}
else {
if(globalButtons[gb].attachEvent) { //IE before version 9
globalButtons[gb].attachEvent("onmousedown",function(){flagSpecialScrollOnRefresh()});
}
}
}
else { continue; }
}
This code is located in a function called attachButtonListeners
Next, I defined my handler like so and placed it into another function that gets called each time my page is being loaded -
function checkSpecialScrollCase() {
var spfrm = getPortlet();
var sp_doc = spfrm.contentDocument ? spfrm.contentDocument: spfrm.contentWindow.document;
var specialScrollExists = sp_doc.getElementById(docTypeButton).value;
if (specialScrollExists == "YES") {
sp_doc.getElementById(docTypeButton).value = 'NO';
}
// else - nothing to do in this case
}
docTypeButton = REQS_BUTTONS
And it references the following element at the bottom of my JSP page -
<input type="hidden" id="REQS_BUTTONS" value="NO"/>
<a name="anchorREQS"></a>
Notice the anchor tag. Eventually, I need to add the location.hash call into my handler so that I scroll to this location. That part is irrelevant at this point and here is why.
Problem -
My flagSpecialScrollOnRefresh function is NOT setting the value to YES when it should be.
I believe my onClick event is happening too fast for my onmousedown event from happening.
Evidence -
If I place an alert statement like so -
function flagSpecialScrollOnRefresh() {
var scfrm = getPortlet();
var sc_doc = scfrm.contentDocument ? scfrm.contentDocument: scfrm.contentWindow.document;
alert("BLAH!");
sc_doc.getElementById(docTypeButton).value = "YES";
}
And then I examine the element using Firebug - the value is getting SET!
Once I take out the alert - no go!
How do I ensure that my mousedown event gets executed first? Or is this even the problem here????
mousedown is part of a click event.
Whatever you are doing with click events now should be moved to the submit event on the form. That way you can use mousedown, mouseover, or even click on the buttons to do whatever you want.

Categories

Resources