javascript do something only once - javascript

i have the following function which lets my elements bounce every time i click on them. how can i achive that i can only click once on each element and if i click a second time to get an alert ("already clicked me")?
// Bounce On Click
function bounceOnClick(view) {
// If the view is a normal view (not a scrollview)
if (view instanceof View) {
// Listen to a click event
view.on("click", function (event) {
// Stop sending the click event to underlying views after this
event.stopPropagation()
// "Wind up" the spring
view.scale = 0.7
// And scale back to full size with a spring curve
view.animate({
properties: {
scale: 1.0
},
curve: "spring(1000,15,500)"
})
})
}
}
// Loop through all the exported views
for (var layerGroupName in PSD) {
bounceOnClick(PSD[layerGroupName]);
}

In JavaScript all objects are dynamic, so you can add properties to view:
view.on("click", function (event) {
if (this.clicked) {
alert("already clicked!");
} else {
// your code
this.clicked = true;
}
});

You can use jquery .one()
Jquery .one() :- Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
Try this :
view.one("click", function (event) {
// Your Code
});

Something like this should do it:
function bounceOnClick(view) {
if (view instanceof View) {
// Listen to a click event, and run this handler only once.
view.one("click", function (event) {
event.stopPropagation();
view.scale = 0.7;
view.animate({
properties: {
scale: 1.0
},
curve: "spring(1000,15,500)"
})
// New event handler: notify the user the element was clicked before.
view.on("click", function (event) {
event.stopPropagation();
alert("already clicked me!");
})
})
}
}
This uses jQuery's .one() event handler to run the first function only once, and then assigns a new event handler with the "already clicked me!" alert.

Related

Bind custom event to dynamic created elements

I've been binding events to dynamically created elements without any kind of issues by using:
$(document).on(event, element, function)
Now I want to bind a custom event and I just can´t get it to work.
The event is a JS plugin to handle single e double click. If I use it like this:
$('#test').oneordoubleclick({
oneclick: function () {
alert('you have clicked this node.');
},
dblclick: function () {
alert('you have double clicked this node.');
}
});
It works like a charm, but, as I transform the code to bind the event to dynamically created elements, like this:
$(document).on('oneordoubleclick', '#test', {
oneclick: function () {
alert('you have clicked this node.');
},
dblclick: function () {
alert('you have double clicked this node.');
}
});
It stops working!
It wasn't supposed to work? What am i doing wrong? It is possible to do what i want to accomplish?
According to my understanding, .oneordoubleclick is not an Event, just like .footable or .tooltip. Therefore, you cannot put it in $(document).on("oneordoubleclick","#test", ...)
Here's my solution, with the aid of the plugin source code:
// Custom functions
let singleClick = function () { // your function when is single click
alert('you have clicked this node.');
}
let doubleClick = function () { // your function when is double click
alert('you have double clicked this node.');
}
// Necessary to differentiate is single or double click
let timer,
do_click = function (e, fx) {
clearTimeout(timer);
timer = setTimeout(function () {
fx();
}, 400); // if there is no another click between 0.4s, then it is single click
},
do_dblclick = function (e, fx) {
clearTimeout(timer); // the single click function will not be called
fx();
};
// Listener
$(document) .on("click", "#test", function (e) { do_click(e, singleClick) })
.on("dblclick", "#test", function (e) { do_dblclick(e, doubleClick) })
Correct me if I'm wrong.
In addition to the correct answer, i needed to know which DOM element was responsible for the call. To achieve that i changed a little bit XH栩恒 answer code...
// Necessary to differentiate is single or double click
let timer,
do_click = function (e, fx, element) {
clearTimeout(timer);
timer = setTimeout(function () {
fx(element);
}, 400); // if there is no another click between 0.4s, then it is single click
},
do_dblclick = function (e, fx, element) {
clearTimeout(timer); // the single click function will not be called
fx(element);
};
// Listener
$(document).on("click", ".teste", function (e) {
do_click(e, singleClick, $(this))
})
.on("dblclick", ".teste", function (e) {
do_dblclick(e, doubleClick, $(this))
})
let singleClick = function (element) { // your function when is single click
console.log(element)
}
let doubleClick = function (element) { // your function when is double click
console.log(element)
}

How to disconnect the current event only in jQuery?

I have the following event:
$(document).on('scroll', function() {
// do stuff
});
At the completion of this event, I want to disconnect it. I can do $(document).off('scroll');, but that will disconnect all the scroll events (there are several) on the page.
How do I disconnect just this one event?
How do I disconnect just this one event?
by .namespacing it!
$(document).on({
"scroll.myNamespace" : function() {
// do stuff
}
});
than at some point you can either
$(document).off("scroll.myNamespace");
or all your namespaced events (if you have more of them, like i.e: scroll.myNamespace, click.myNamespace etc...)
$(document).off(".myNamespace");
Example: how to off a namespaced event
$(document).on({
"scroll.teapot": function() {
console.log("TEAPOT!")
},
scroll: function() {
console.log("scroll")
}
});
$("#offTeapot").on({
click: function() {
$(document).off(".teapot"); // off every ".teapot" namespaced event
}
})
body {
height: 400vh;
}
button {
position: fixed;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="offTeapot">OFF TEAPOTS</button>
<h1>SCROLL!!!!!</h1>
In order to remove a specific handler using off(), you'll need to pass a reference to the handler, so simply declare your handler function and pass the reference to both on() and off():
function scrollHandler() {
// do stuff
}
$(document).on('scroll', scrollHandler);
$(document).off('scroll', scrollHandler);
The .off() method removes event handlers that were attached with .on(). See the discussion of delegated and directly bound events on that page for more information. Calling .off() with no arguments removes all handlers attached to the elements. Specific event handlers can be removed on elements by providing combinations of event names, namespaces, selectors, or handler function names.
http://api.jquery.com/off/
You can separate the call back and put it into its own function, then you can remove it.
function doScroll(){
// Do stuff
}
// Add the function
$(document).on('scroll', doScroll);
// Remove the function
$(document).off('scroll', doScroll);
Did you try setting it specifically?
$(document).on('scroll', '#yourId', function(){
}).off('scroll', '#yourId', function(){
});
How about setup a global flag for one time usage:
var doThis = true;
$(document).on('scroll', function() {
if(doThis){
// do stuff
doThis = false;
}
});

Referring to tooltip within event listener to keep it open on hover

Finding myself in a bit of a strange position where I have to reference the tooltip within an instantiation for all tooltips.
$('body').tooltip({
selector: '[data-toggle="tooltip"]',
html: true,
animation: false,
}).on("mouseenter", function (e) {
e.stopPropagation();
var _this = e.target;
$(_this).tooltip("show");
$(".tooltip").on("mouseleave", function () {
$(_this).tooltip('hide');
});
}).on("mouseleave", function (e) {
e.stopPropagation();
var _this = e.target;
setTimeout(function () {
if (!$(".tooltip:hover").length) {
$(_this).tooltip("hide");
}
}, 300);
});
That being said, how can I:
Reference the actual element that is triggering this jQuery call
Keep the tooltip open while either the actual tooltip or element that generated it are being hovered over?
Here is a link to a JSFiddle prototype:
https://jsfiddle.net/cwv57weu/8/
Within your '.on()' call, you can add an 'event' argument to your anonymous function. This will contain all of the data from the event including the element which triggered the event (it will be referenced as 'target').
}).on("mouseenter", function (event) {
$(event.target).tooltip("show");
})
the event argument contains a ton of data, I would play around with it by console.log(event) within your anonymous function to get a feel as to what data is available to you.
Use event.target.
$('body').tooltip({
selector: '[data-toggle="tooltip"]',
html: true,
animation: false,
}).on("mouseenter", function (e) {
var _this = e.target;
$(_this).tooltip("show");
$(".tooltip").one("mouseleave", function () {
$(_this).tooltip('hide');
});
}).on("mouseleave", function (e) {
var _this = e.target;
setTimeout(function () {
if (!$(".tooltip:hover").length) {
$(_this).tooltip("hide");
}
}, 300);
});
e.target is the actual element that the event originated on, while this is the element that the event listener was attached to (equivalent to e.currentTarget).
Note that because of event bubbling, the event will fire on all the containing elements up to body. You may want to use e.stopPropagation() to prevent bubbling, so you only process the deepest element.
I also changed the mouseleave handler on .tooltip to use .one(). Otherwise, every time you enter something, you'll add another mouseleave handler to all the tooltips, without removing the previous one, and soon there will be thousands of handlers running (this is why it's generally wrong to bind event handlers inside other event handlers). I'm not really sure you need both that mouseleave handler and the one you attach to body.

Pause mouseup/click until $.get is done

On my client page I want to execute my function each time user click something. Function send this element tag name to database. To avoid overwriting client page click event handlers I use mousedown. My idea:
jQuery('body').on('mousedown', function(event){
var that = event.target,
thatTag = event.target.nodeName;
jQuery.get(
"http://example.com",
{ parameter: thatTag },
function() {
//It hasn't time to execute, because mouseup is auto executed and click action change location (if I click anchor)
}
);
});
So, is there any option to pause/block mouseup/click until my GET action is done?
You need to use .off to unbind your mousedown handler when it is first executed, then re-bind once again when the .get function completes:
$(function() {
// On page load, bind the first instance of the event
$("body").on("mousedown", handleMouseDown);
});
function handleMouseDown(event) {
// Detach the event so that is isn't handled again until the .get finishes
$("body").off("mousedown", handleMouseDown);
var that = event.target,
thatTag = event.target.nodeName;
jQuery.get(
"http://example.com",
{ parameter: thatTag },
function() {
// Re-attach the event now that the .get has finished
$("body").on("mousedown", handleMouseDown);
}
);
}

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
};

Categories