Calling JS functions from Href - javascript

I'm curious whats the best way to call a JS function with a href link in HTML. I don't use a library and i see alot of mention about jquery using event handlers ...
But if im not using a library can it still be done or will i have to use an on click type call ?

You can use event handlers with plain javascript. No framework is required. Here's a cross browser function I use:
// add event cross browser
function addEvent(elem, event, fn) {
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent("on" + event, function() {
// set the this pointer same as addEventListener when fn is called
return(fn.call(elem, window.event));
});
}
}
And, an example of using it would be like this:
HTML:
<a id="myLink" href="#">Click ME</a>
Javascript:
var link = document.getElementById("myLink").
addEvent(link, "click", function(e) {
// process the click on the link here
});
If you don't want the default click of a link to happen, then you need to prevent the default behavior from the event handler like this:
var link = document.getElementById("myLink").
addEvent(link, "click", function(e) {
// process the click on the link here
// prevent default action of the click
if (e.preventDefault) {
e.preventDefault(); // normal browsers
} else {
e.returnValue = false; // older versions of IE (yuck)
}
});

try this
function test() { alert (''); }
<a href="#" onclick="test();" />

Basically there are two ways:
...
and
...
(in this case someFunction must return false)
I prefer the latter.

Related

jQuery calling on() on dynamically generated it after calling click()

I am trying to develop some code to allow the user show/hide a block level element by clicking a button.
The HTML structure is like below
<div class="chat_container"><a class="crm" href="https://google.com" target="_blank">Chat?</a><button id="close_chat"><</button></div>
I have written a click() function for #close_chat which amongst other things changes the ID of the button to #open_chat. I then use the on() method on #open_chat to modify some classes and ids on various elements. In isolation both these methods work, however when combined they don't work. I have noticed that when I click #close_chat even though the ID changes to #open_chat the original event is still attached to the button. After doing some search I suspected the issue might have been related to events bubbling up, but now I am not so sure, still I added event.stopPopagation() to my click function and I can see it appears to be called correctly. I have also tried using the one() method, this appeared to get closer to the behavior I was expecting at the DOM level but still didn't working
My expected behavior is the click() function is called when the user clicks #close_chat, the event is then unbound allowing the .on() event to be called on #open_chat. Id than of course have to reset the original functionality. My code looks like this
$(document).ready(function () {
var close = "<button id='close_chat'><</div>";
var container = $("<div />");
container.addClass("chat_container");
var crmChat = $("<a />");
crmChat.addClass("crm");
crmChat.attr("href", "https://google.com");
crmChat.attr("target", "_blank");
crmChat.text("Chat?");
console.log(crmChat);
console.log(container);
$(container).insertAfter("#heading");
$(container).prepend(crmChat);
$(close).insertAfter(crmChat);
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
});
any help is greatly appreciated
Sam
edit, I have now updated my code to look like so
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
function attachOpendChatListener() {
$(".chat_container").on("click","#open_chat", function () {
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<")
$(".crm_chat_container").removeClass("animate-close").addClass("animate-open");
});
//attachClosedChatListner();
}
function attachClosedChatListner() {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">")
$(".chat_container").removeClass("animate-open").addClass("animate-close");
//attachOpendChatListener();
}
What about re-attaching the event?
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
attachOpenChatListener();
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
function attachOpenChatListener() {
$("#close_chat").off('click');
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
}
I managed to work this out, the click function was causing the problem
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
I've replaced it with .on and it works now
$(".crm_chat_container").on("click", "#close_chat", function (event) {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">");
$(".crm_chat_container").removeClass("primo-animate-open").addClass("animate- close");
attachCloseChatListener();
event.stopImmediatePropagation();
});
function attachCloseChatListener() {
$(".crm_chat_container").on("click", "#open_chat", function (event) {
$("#open_chat").off('click');
$(".crm_chat_container").removeClass("primo-animate-close").addClass("primo-animate-open");
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<");
event.stopImmediatePropagation();
});
}
on thing is my click events appears to be firing multiple times, that is after clicking my buttons a few times I see several click events in dev tools.
Anyway, thanks for putting me on the right path

Actually do default after preventing default

I want to prevent default behavior of a link (a) then do the default behavior, let's say open open a link in a new window.
Here is some HTML code:
<a href="somewhere" target="_blank" id="mylink">
And the JS code:
document.getElementById('mylink').addEventListener('click', function (e) {
e.preventDefault();
axios.post('options', new FormData(document.querySelector('#myform')))
.then(function(){
// Here I want to do what the link should have done!
});
});
I know I can do something like this:
window.open(e.target.href);
But it's not an option because the browser consider this as a popup. And I don't want to rewrite something in JS, just consider the link as usual: this link has to do its default behavior (which was prevented).
Is there a way to do this?
Here is some idea:
var openingPopup = false;
document.getElementById('mylink').addEventListener('click', function (e) {
if(!openingPopup){
e.preventDefault();
axios.post('options', new FormData(document.querySelector('#myform')))
.then(function(){
// make sure this would not run twice
openingPopup = true;
document.getElementById('mylink').click();
});
}else{
// skipping this only for one time
openingPopup = false;
}
});
This way,
you run the popup opener click handler once,
then prevent the others,
trigger the click event again manually,
this time do nothing, but allow others to run.
As per #Electrox-Qui-Mortem 's suggested link, after you complete your pre-process(es), you can remove the event listener and call the click again.
(relevant MDN link: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener )
const anchor = document.getElementById('anchor');
anchor.addEventListener('click', test);
function test(e){
e.preventDefault();
alert('test');
if( true ){
console.log( this );
this.removeEventListener('click', test);
this.click();
}
}
<a id="anchor" href="https://www.google.com">Test</a>
It's got wonky performance inside code testing tools (like JSfiddle and CodePen) -- you would have to test it in your actual application to make sure if it works appropriately for your use case.
I've only had good results with removeEventListener when referencing an outside function as the "listener" func. In this case test()
In a more "native" way you could create a new "click" event which is not cancelable and trigger it against the same element.
var anchor = document.querySelector('#target');
function triggerClick(target) {
var newClick = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: false
});
target.dispatchEvent(newClick);
}
anchor.addEventListener('click', function(e) {
e.preventDefault();
if(e.defaultPrevented) {
alert('Prevented!');
triggerClick(anchor);
}
else {
alert('Not prevented');
}
});
Click me!
Here the key is the cancelable: false in the new event created in the function triggerClick(target), which bypass the e.preventDefault().
In the embedded example on StackOverflow it doesn't work, but here's a JSFiddle!

JavaScript - Hook in some check on all 'click' events

So I have a regular onclick event attached to a few buttons, each function that handles the onclick event does something different (so I can't reuse the same function for both events).
element1.onclick = function() {
if(this.classList.contains('disabled') {
return false;
}
// For example make an AJAX call
};
element2.onclick = function() {
if(this.classList.contains('disabled') {
return false;
}
// For example hide a div
};
I'm writing duplicate code for this 'disabled' class check, I want to eliminate this by hooking in some common onclick check then fire the regular onclick event if that check passes.
I know the below won't work but I think it will illustrate what I'm trying to do:
document.addEventListener('click', function() {
// 1. Do the disabled check here
// 2. If the check passes delegate the event to the proper element it was invoked on
// 3. Otherwise kill the event here
});
I'm not using any JavaScript library and I don't plan to, in case someone comes up with 'Just use jQuery' type answers.
EDIT: Had to pass boolean third argument to addEventListener as true and everything is fine.
Use event capturing, like so:
document.addEventListener('click', function(event) {
if (/* your disabled check here */) {
// Kill the event
event.preventDefault();
event.stopPropagation();
}
// Doing nothing in this method lets the event proceed as normal
},
true // Enable event capturing!
);
Sounds like you need to set the capture flag to true and then use .stopPropagation() on the event if a certain condition is met at the target, f.ex:
document.addEventListener('click', function(e) {
if ( condition ) {
e.stopPropagation();
// do soemthing else, the default onclick will never happen
}
}, true);​​​​​​​​​​​​​​​​​​​​​​
Here is a demo: http://jsfiddle.net/v9TEj/
You can create a generic function that receives a callback:
//check everything here
function handleOnclick(callback) {
if(this.classList.contains("disabled")) {
return false;
} else {
callback(); //callback here
}
}
//and now on every onclick, just pass the custom behavior
element1.onclick = function() {
handleOnClick(function() {
console.log('element1 onclick fire'); // For example hide a div
});
};
element2.onclick = function() {
handleOnClick(function() {
console.log('element2 onclick fire'); // For example ajax request
});
};
Edit
Based on your latest comment, let me know if this rewrite works for you... only one biding this time.
element1.customFunction = function() {
handleOnClick(function() {
console.log('element1 onclick fire'); // For example hide a div
});
};
element2.customFunction = function() {
handleOnClick(function() {
console.log('element2 onclick fire'); // For example ajax request
});
};
document.addEventListener('click', function() {
//1. grab the element
//2. check if it has the customFunction defined
//3. if it does, call it, the check will be done inside
};

Event listener loop

How do I add a listener for hovering over div tags like this:
btn1
btn2
btn3
btn4
I want to add a listener that loops through them like I show below and then applies a function if it has mouseover.
function listen() {
for (i=1;i<=10;i++) {
wat = document.getElementById('btn'+i);
wat.addEventListener('mouseover',functionwat,false );
}
}
I have this and its not working, and yes it is calling the function listen(), because I added an alert thing in there to make sure its working correctly, and functionwat works right too. Any idea what I'm doing wrong?
What browser are you using? Registering event handlers is different browser to browser. PPK has some good discussion of browser events here.
In short, this is the cross-browser code for adding a handler.
function addEventSimple(obj,evt,fn) {
if (obj.addEventListener)
obj.addEventListener(evt,fn,false);
else if (obj.attachEvent)
obj.attachEvent('on'+evt,fn);
}
Now you can attach the event with
function listen() {
for (i=1;i<=10;i++) {
wat = document.getElementById('btn'+i);
addEventSimple(wat, 'mouseenter', functionwat);
}
}
Instead of looping for each item and attaching events, look into implementing event delegation. As it relates your situation, let assume you use jQuery and your buttons' markup is as followed:
<div id="btnList">
<button id="btn1">btn1</button>
<button id="btn2">btn2</button>
<button id="btn3">btn3</button>
<button id="btn4">btn4</button>
</div>
JavaScript:
$(document).ready(function()
{
$("#btnList button").bind(
"mouseenter mouseleave",
function(e) {
//do something based on target/id
alert(this.id);
});
});
It seems that you might be somewhat messy with your variables. For instance, you do not use var to declare i, so it might end up in the global namespace. Following this, are you sure functionwat is really a function at the time listen() executes?
You could check that by;
function listen() {
if(typeof functionwat !== "function") {
alert("functionwat is not a function, but a " + typeof functionwat);
}
for (var i = 1; i <= 10; ++i) {
wat = document.getElementById("btn"+i);
wat.addEventListener("mouseover", functionwat, false);
}
}
David,
You're not having any luck because, I am almost positive you are using a browser which is not IE. Your events will not fire in a non-IE browser because the event "mouseenter" is only exposed in IE. To make it work, you need to change "mouseenter" to use "mouseover".
function listen() {
for (i=1;i<=10;i++) {
wat = document.getElementById('btn'+i);
addEventSimple(wat, 'mouseenter', functionwat);
}
}
to
function listen() {
for (i=1;i<=10;i++) {
wat = document.getElementById('btn'+i);
if(wat) { addEventSimple(wat, 'mouseover', functionwat); }
}
}

How to write onshow event using JavaScript/jQuery?

I have an anchor tag on my page, I want an event attached to it, which will fire when the display of this element change.
How can I write this event, and catch whenever the display of this element changes?
This is my way of doing on onShow, as a jQuery plugin. It may or may not perform exactly what you are doing, however.
(function($){
$.fn.extend({
onShow: function(callback, unbind){
return this.each(function(){
var _this = this;
var bindopt = (unbind==undefined)?true:unbind;
if($.isFunction(callback)){
if($(_this).is(':hidden')){
var checkVis = function(){
if($(_this).is(':visible')){
callback.call(_this);
if(bindopt){
$('body').unbind('click keyup keydown', checkVis);
}
}
}
$('body').bind('click keyup keydown', checkVis);
}
else{
callback.call(_this);
}
}
});
}
});
})(jQuery);
You can call this inside the $(document).ready() function and use a callback to fire when the element is shown, as so.
$(document).ready(function(){
$('#myelement').onShow(function(){
alert('this element is now shown');
});
});
It works by binding a click, keyup, and keydown event to the body to check if the element is shown, because these events are most likely to cause an element to be shown and are very frequently performed by the user. This may not be extremely elegant but gets the job done. Also, once the element is shown, these events are unbinded from the body as to not keep firing and slowing down performance.
You can't get an onshow event directly in JavaScript. Do remember that the following methods are non-standard.
IN IE you can use
onpropertychange event
Fires after the property of an element
changes
and for Mozilla
you can use
watch
Watches for a property to be assigned
a value and runs a function when that
occurs.
You could also override jQuery's default show method:
var orgShow = $.fn.show;
$.fn.show = function()
{
$(this).trigger( 'myOnShowEvent' );
orgShow.apply( this, arguments );
return this;
}
Now just bind your code to the event:
$('#foo').bind( "myOnShowEvent", function()
{
console.log( "SHOWN!" )
});
The code from this link worked for me: http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
$('#foo').on('show', function() {
console.log('#foo is now visible');
});
$('#foo').on('hide', function() {
console.log('#foo is hidden');
});
However the callback function gets called first and then the element is shown/hidden. So if you have some operation related to the same selector and it needs to be done after being shown or hidden, the temporary fix is to add a timeout for few milliseconds.

Categories