Can I add onmouseover attribute to run only once? - javascript

Say I have a link like the following:
<a class="link" href="www.rich.com" onmouseover="go(this)">Link</a>
Is there a way to configure the onmouseover event, calling go(this) to run only a single time while still using the inline onmouseover=<some code> notation? I want it defined inline, not with a JavaScript call.
Currently, I have this, but it is not what I want:
$(".link").one('mouseover', function(e) {
// do something
});

You can nullify the onmouseover binding afterwards:
<a class="link" href="www.rich.com" onmouseover="go(this); this.onmouseover = null;">Link</a>

Using Vanilla JS:
const link = document.querySelector('.link');
link.addEventListener('mouseover',
() = window.open('your url'),
{ once : true }
);
ref: How can I add an event for a one time click to a function?

You could set a var that indicates whether it has been triggered or not...
var triggered = false;
$(".link").one('mouseover', function(e) {
// do something
if(!triggered)
{
triggered = true;
// and whatever else you want to do
}
});

Alternatively you can do something like this :
var check = 0;
$(".link").on('mouseover', function(e) {
if(check == 0 ){
// do something
check = 1;
}else {
return false;
}
});

Related

How can I modify an anonymous javascript function with tampermonkey?

Here is the block of code I want to replace:
$(document).ready(function () {
$(".button-purple").click(function () {
interval = $(this).attr('id');
name = $(this.attr('name');
if(Number($(this).val()) === 0) {
if(name == 'static') {
do this
}
else {
do this
}
}
else {
do this
}
});
});
I can't find any documentation on trying to replace the function since it's unnamed though. Is it possible to replace the entire javascript file + delete the line loading it / insert my own script? Would really appreciate any help I can get.
If you just want to remove the click event handler, then simply say
var $element = $(".button-purple");
$element.off('click');
If you want to Remove all the event handlers, then you'll first have to find out what all event handlers are present and then remove them iteratively.
var element = $element[0]; //Make sure the element is a DOM object and not jQuery Object.
// Use this line if you're using jQuery 1.8+
var attachedEvents = $._data(element,'events');
// Use this line if you're using jQuery < 1.8
var attachedEvents = $(element).data('events'); //Here you can also replace $(element) with $element as declared above.
for(var event in attachedEvents){
$element.off(event);
}
UPDATE:
You can simply add your own event handler (using .on() API) after you're done removing all the required existing handlers.
Just define your function.
function yourFunction(){ /* your code */};
$element.on('click', yourFunction);
Update 2:
Since you just want to remove the click event handler, this is the simplest code that will serve your purpose.
$(".button-purple").off('click').on('click', yourFunction);
I'm not aware of tampermonkey, but you can try this:
function chickHandler() {
interval = $(this).attr('id');
name = $(this.attr('name');
if (Number($(this).val()) === 0) {
if (name == 'static') {
do this
} else {
do this
}
} else {
do this
}
}
}
function onReadyHandler() {
$(".button-purple").click(chickHandler);
}
$(document).ready(onReadyHandler);
When you do something like .click(function(){...}), here function is called as a callback. You have to send a function as a callback. Not necessary to be anonymous.

Jquery preventDefault(return false;) doesnt work always

I have this piece of code and i can't prevent default link event all the time. It's working like 90% of the times, but the rest 10% my code doesn't run, get no error message and put a # on the end of my url. I have # on my href on my a tag.
I use .on() because sometimes the element is loaded after the document is ready. And i use .off() because before i used it, sometimes triggered more than once when i clicked on it. The strange part is sometimes. I don't get it how can a code sometimes work and sometimes dont. Shouldn't be the same result all the time?
Sorry for the lot of comments.
Here is my full jquery code:
//Handle box opening and closing
var boxcontent_width = $(".box-content").css("width");
$(".boxarrow").addClass("done");
$(document).on("click",".boxarrow", function(event){
var serial = $(this).parent().parent().attr("serial");
var clink = $(document).find("[comment-link='"+serial+"']");
if(clink.hasClass("open")){
clink.click();
}
if($(this).hasClass("done")){
$(this).removeClass("done");
$(document).find("#comment-box"+$(this).parent().parent().attr("serial")).slideUp(250);
if($(this).parent().parent().find(".box-content").is(":hidden")){
$(this).attr("src","source/up_arrow.png");
}else{
$(this).attr("src","source/down_arrow.png");
}
$(this).parent().parent().find(".box-content").slideToggle(500,function(){
$(this).parent().find("div img").addClass("done");
});
}
return false;
});
//Handle votes
$(document).on("click","#positive-button, #negative-button", function(event){
var serial = $(this).parents(".tutorial-box").attr("serial");
var vote = 0;
if($(this).attr("id") == "positive-button"){
vote = 1;
}
$.post("vote.php",{
php_tutorial_id: serial,
php_vote_value: vote
},function(data){
if(data.localeCompare("error") && data){
if(data > 9999)data = 9999;
if(data < -9999)data = -9999;
if(data > 0){
data = "+"+data;
}
$("#tutorial-vote"+serial+" p").fadeOut(250, function(){
$("#tutorial-vote"+serial+" p").html(data).fadeIn(250);
});
}
});
return false;
});
//Handle comment opening and closing
$(document).on("click",".showcomments", function(event){
if($(this).hasClass("open")){
$(this).html("<p>Show comments</p>");
$(this).removeClass("open");
}else{
$(this).html("<p>Hide comments</p>");
$(this).addClass("open");
}
var clink = $(this).attr("comment-link");
var is_open = $(this).hasClass("open");
$(this).parents().find("#"+clink).slideToggle(500);
return false;
});
//Handle add comment button
$(document).on("click",".comment-button", function(event){
var serial = $(this).attr("serial");
serial = "#comment-box"+serial;
$(document).find(".comment-box").not(serial).slideUp(250);
$(document).find(serial).slideToggle(250);
return false;
});
$(document).on("click",".comment-box-submit", function(event){
var tutorial_id = $(this).parent().attr("serial");
var comment_text = $(this).parent().find(".comment-box-area");
var serial = $(this).parent().attr("serial");
$.post("send_comment.php",{
php_tutorial_id: tutorial_id,
php_comment_text: comment_text.val()
},function(data){
$(document).find("#comment-response"+serial).fadeOut(500, function(){
if(data){
$(document).find("#comment-response"+serial).html(data);
$(document).find("#comment-response"+serial).fadeIn(500);
}else{
$(document).find("#comment-response"+serial).html("");
$.post("reflesh_comments.php",{
php_tutorial_id: tutorial_id
},function(data){
if($(document).find("#"+tutorial_id).is(":hidden")){
$(document).find("#"+tutorial_id).html(data);
}else{
$(document).find("#"+tutorial_id).fadeOut(500, function(){
$(document).find("#"+tutorial_id).html(data);
$(document).find("#"+tutorial_id).fadeIn(500);
});
}
});
$(document).find("#comment-response"+serial).html("");
comment_text.val("");
}
});
});
return false;
});
$(document).on("click",".comment-remove", function(event){
var serial = $(this).attr("serial");
var tutorial_serial = $(this).parent().parent().parent().attr("id");
$("#overlay-box").load("overlay_boxes/remove_comment.php", { php_serial: serial, php_tutorial_serial: tutorial_serial }, function(){
$("#overlay-box").fadeIn(250);
$("#overlay").fadeIn(250);
});
return false;
});
$(document).on("click",".comment-reply", function(event){
var serial = $(this).parent().parent().attr("serial");
var owner = $(this).parent().parent().find(".comment-owner").html();
var owner_id = $(this).attr("serial");
$(document).find("#comment-box"+serial).find(".comment-response").hide();
$(document).find("#comment-box"+serial).slideDown(250);
$(document).find("#comment-box"+serial).find(".comment-box-area").val("#"+owner+": ");
$(document).find("#comment-box"+serial).find(".comment-box-area").focus();
return false;
});
$(document).on("click",".comment-report", function(event){
var serial = $(this).attr("serial");
var tutorial_serial = $(this).parent().parent().parent().attr("id");
$("#overlay-box").load("overlay_boxes/report_comment.php", { php_serial: serial }, function(){
$("#overlay-box").fadeIn(250);
$("#overlay").fadeIn(250);
});
return false;
});
You apparently have a multitude of issues, some of which we can't help with because you haven't included the relevant code.
You have your javascript code that attaches the event handler sometimes? executing more than once.
You are attaching the event to an element that may not exist at run time (are you executing the event handler attaching code when you insert it?)
You are removing all event handlers indiscriminately, possibly events that aren't your own.
The second and third problems are easy. Don't use
$(".comment-remove").off().on("click", function(event){
use
$(document).on('click','.comment-remove',function(event){
I would also recommend not using the serial attribute, but use data-serial instead, and instead of var tutorial_serial = $(this).parent().parent().parent().attr("id"); use something like var tutorial_serial = $(this).closest('.tutorial').attr("id"); which is more maintainable.
Remove the href property on your anchor to prevent it from adding a # at the end of your url:
<a href="#" serial="'.$data_id.'" class="comment-remove" '.$hidden_remove.' >Remove</a>
And I would suggest using:
$("body").on("click",".comment-remove",function(){...})
To prevent the event firing more than once, since you are setting the listener on the body once, instead of on, which could or could not be assigned to your ID as desired, depending on wether the element exists in the DOM when that line is ran.

how to get javaScript event source element?

Is there a way to retrieve the element source of an inline javaScript call?
I have a button like this:
<button onclick="doSomething('param')" id="id_button">action</button>
Note:
the button is generated from server
I cannot modify the generation process
several buttons are generated on the page, I have control only on client side.
What I have tried:
function doSomething(param){
var source = event.target || event.srcElement;
console.log(source);
}
On firebug I get event is not defined
Edit:
After some answers, an override of the event handling using jQuery is very acceptable. My issue is how to call the original onClick function with it's original prameters, and without knowing the function name.
code:
<button onclick="doSomething('param')" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button1">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>
.
.
and so on..
So the override would be:
$(document).on('click', 'button', function(e) {
e.preventDefault();
var action = $(this).attr('onclick');
/**
* What to do here to call
* - doSomething(this, 'param'); if button1 is clicked
* - doAnotherSomething(this, 'param1', 'param2'); if button2 is clicked
* - doDifferentThing(this); if button3 is clicked
* there are many buttons with many functions..
*/
});
Your html should be like this:
<button onclick="doSomething" id="id_button">action</button>
And renaming your input-paramter to event like this
function doSomething(event){
var source = event.target || event.srcElement;
console.log(source);
}
would solve your problem.
As a side note, I'd suggest taking a look at jQuery and unobtrusive javascript
You should change the generated HTML to not use inline javascript, and use addEventListener instead.
If you can not in any way change the HTML, you could get the onclick attributes, the functions and arguments used, and "convert" it to unobtrusive javascript instead by removing the onclick handlers, and using event listeners.
We'd start by getting the values from the attributes
$('button').each(function(i, el) {
var funcs = [];
$(el).attr('onclick').split(';').map(function(item) {
var fn = item.split('(').shift(),
params = item.match(/\(([^)]+)\)/),
args;
if (params && params.length) {
args = params[1].split(',');
if (args && args.length) {
args = args.map(function(par) {
return par.trim().replace(/('")/g,"");
});
}
}
funcs.push([fn, args||[]]);
});
$(el).data('args', funcs); // store in jQuery's $.data
console.log( $(el).data('args') );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="doSomething('param')" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button1">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>
That gives us an array of all and any global methods called by the onclick attribute, and the arguments passed, so we can replicate it.
Then we'd just remove all the inline javascript handlers
$('button').removeAttr('onclick')
and attach our own handlers
$('button').on('click', function() {...}
Inside those handlers we'd get the stored original function calls and their arguments, and call them.
As we know any function called by inline javascript are global, we can call them with window[functionName].apply(this-value, argumentsArray), so
$('button').on('click', function() {
var element = this;
$.each(($(this).data('args') || []), function(_,fn) {
if (fn[0] in window) window[fn[0]].apply(element, fn[1]);
});
});
And inside that click handler we can add anything we want before or after the original functions are called.
A working example
$('button').each(function(i, el) {
var funcs = [];
$(el).attr('onclick').split(';').map(function(item) {
var fn = item.split('(').shift(),
params = item.match(/\(([^)]+)\)/),
args;
if (params && params.length) {
args = params[1].split(',');
if (args && args.length) {
args = args.map(function(par) {
return par.trim().replace(/('")/g,"");
});
}
}
funcs.push([fn, args||[]]);
});
$(el).data('args', funcs);
}).removeAttr('onclick').on('click', function() {
console.log('click handler for : ' + this.id);
var element = this;
$.each(($(this).data('args') || []), function(_,fn) {
if (fn[0] in window) window[fn[0]].apply(element, fn[1]);
});
console.log('after function call --------');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="doSomething('param');" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button2">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>
<script>
function doSomething(arg) { console.log('doSomething', arg) }
function doAnotherSomething(arg1, arg2) { console.log('doAnotherSomething', arg1, arg2) }
function doDifferentThing() { console.log('doDifferentThing','no arguments') }
</script>
Cross-Browser solution
I believe the solution by #slipset was correct, and it doesn't need jQuery, BUT it wasn't cross-browser ready.
According to Javascript.info, events (when referenced outside markup events) are cross-browser ready once you assure it's defined with this simple line: event = event || window.event.
So the complete cross-browser ready function would look like this:
function logMySource(param){
event = event || window.event;
var source = event.target || event.srcElement;
console.log("sourceID= "+source.id,"\nsourceTagName= "+source.tagName,"\nparam= "+param);
}
<button onclick="logMySource('myVariable')" id="myID">action</button>
Try it!
I've included returns of useful information of the source.
You can pass this when you call the function
<button onclick="doSomething('param',this)" id="id_button">action</button>
<script>
function doSomething(param,me){
var source = me
console.log(source);
}
</script>
Try something like this:
<html>
<body>
<script type="text/javascript">
function doSomething(event) {
var source = event.target || event.srcElement;
console.log(source);
alert('test');
if(window.event) {
// IE8 and earlier
// doSomething
} else if(e.which) {
// IE9/Firefox/Chrome/Opera/Safari
// doSomething
}
}
</script>
<button onclick="doSomething('param')" id="id_button">
action
</button>
</body>
</html>
USE .live()
$(selector).live(events, data, handler);
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
$(document).on(events, selector, data, handler);

Detecting Href Is Clicked

I'm trying to detect if certain element is clicked on onbeforeunload. I can't get it to work. Below is examples of the Javascript code and HTML code on the project (Please note that I have no control over the HTML element as it is not my site)
function checkLeave() {
var p = document.getElementByElementById('yeah');
if (p.href.onclick) {
//do something
}
else {
//do something else
}
}
window.onbeforeunload = checkLeave;
HTML CODE
//The goSomewhere goes to another page
<a id="yeah" href="javascript:goSomewhere();">
<img src="smiley.png">
</a>
Thanks in advance,
J
What you need to do is bind an event handler to each on the page.
This can be done with the following:
// Select all links
//var allLinks = document.querySelectorAll('a[href]');
var allLinks = document.links;
// Bind the event handler to each link individually
for (var i = 0, n = allLinks.length; i < n; i++) {
//allLinks[i].addEventListener('click', function (event) {});
allLinks[i].onclick = function () {
// Do something
};
}
You are testing for the presence of the onclick property to the <a> tag. It isn't present in the markup. Rather than using the onclick, the markup calls a script as the element's href. So you need to look for a script in the href instead:
var p = document.getElementByElementById('yeah');
if (p.href.indexOf("javascript") === 0) {
//do something
}
else {
// do something else
}
Maybe something like this? (just the idea)
document.getElementById('yeah').onclick = function() {
clicked = this.href;
};

Do something on :target with javascript

I'm using the CSS3 :target pseudo selector to create in-page navigation without reloading the page. This works really well!
But I have a problem, I need to reset the forms in a page when the page targetted, how can I know if an element is targetted with javascript? Like element.ontarget = function();
Or maybe something like element.ondisplaychange -> element.oncsschange?
BETTER UPDATE:
var hashcache = document.location.hash;
window.onhashchange = function() {
if(hashcache != document.location.hash) {
$(hashcache + ' form input').each(function() {
$(this).val('');
});
hashcache = document.location.hash;
}
}
UPDATE:
$('a[href^="#"]').each(function() {
this.onclick = function() {
href = $(this).attr('href');
if(href != document.location.hash) {
$(href + ' form input').each(function() {
$(this).val('');
});
}
}
});
If you're using JavaScript for the navigation, I'd suggest just adding the check to that. But I'm guessing from your question you're not, that you're instead using plain links with just anchors (e.g., <a href='#target1'>, <a href='#target2'>, ...).
A couple of options:
Use a Timer
In that case, basically what you want to do boils down to receiving an event when the anchor changes. As far as I know, and as far as the people answering this other question on StackOverflow in January knew, you can only do that with a timer. (Edit: But see ide's comment below, there's a new hashchange event we'll be able to use soon!) E.g.:
(function() {
var lastHash = window.location.hash;
setTimeout(function() {
var newHash = window.location.hash;
if (newHash !== lastHash) {
lastHash = newHash;
// Trigger your target change stuff
}
}, 250);
})();
That checks for changes every quarter second. That may not be enough for you, you could lower the 250, but beware running too much and slowing everything else down.
But as you say below, this is inefficient.
Hook the Link's click event
Since you're already using JavaScript on the page, I'd recommend using handlers on your links instead. If you add a class name or something to them (I bet they already have one; I'll us "navlink" below), this is easily set up:
var links, index, link;
links = document.getElementsByTagName('a');
for (index = 0; index < links.length; ++index) {
link = links.item(index);
if ((" " + link.className + " ").indexOf(" navlink ") >= 0) {
hookEvent(link, 'click', clickHandler);
}
}
function clickHandler() {
// `this` will reference the element that was clicked
}
// The 'hook' function:
var hookEvent = (function() {
var elm = document.createElement('a');
function hookEventViaAttach(element, event, handler) {
element.attachEvent("on" + event, handler);
}
function hookEventViaAddListener(element, event, handler) {
element.addEventListener(event, handler, false);
}
function hookEventDOM0(element, event, handler) {
element["on" + event.toLowerCase()] = handler;
}
if (elm.attachEvent) {
return hookEventViaAttach;
}
if (elm.addEventListener) {
return hookEventViaAddListener;
}
// I usually throw a failure here saying not supported, but if you want,
// you can use the DOM0-style stuff.
return hookEventDOM0;
})();
A lot of the complication of the above goes away if you use a library like jQuery, Prototype, YUI, Closure, or any of several others.
For instance, the jQuery version:
$("a.navlink").click(clickHandler);
function clickHandler() {
// `this` will reference the element that was clicked
}
The Prototype version:
$$("a.navlink").invoke('observe', 'click', clickHandler);
function clickHandler() {
// `this` will reference the element that was clicked
}
The onfocus property returns the onFocus event handler code on the current element.
event handling code = element.onfocus
The onblur property returns the onBlur event handler code, if any, that exists on the current element.
element.onblur = function;
Example: http://jsfiddle.net/g105b/cGHF7/
<html>
<head>
<title>onblur event example</title>
<script type="text/javascript">
var elem = null;
function initElement()
{
elem = document.getElementById("foo");
// NOTE: doEvent(); or doEvent(param); will NOT work here.
// Must be a reference to a function name, not a function call.
elem.onblur = doEvent;
};
function doEvent()
{
elem.value = 'Bye-Bye';
alert("onblur Event detected!")
}
</script>
<style type="text/css">
<!--
#foo {
border: solid blue 2px;
}
-->
</style>
</head>
<body onload="initElement()";>
<form>
<input type="text" id="foo" value="Hello!" />
</form>
<p>Click on the above element to give it focus, then click outside the
element.<br /> Reload the page from the NavBar.</p>
</body>
</html>
Maybe youcan just code like this
function hashChangeEvent(){
$(window.location.hash)//do something
}
window.onhashchange = hashChangeEvent;//when hash change
hashChangeEvent();//first load

Categories

Resources