I have dynamically created increment and decrement buttons for certain <input> html elements (specifically for numeric inputs), however I cannot for the life of me how to figure out how to bind an action through the plugin function.
I want to do it specifically this way as these arrows will be used on many different types of forms that minus and add values (e.g. %, money etc.) which affect certain visual elements.
The function looks around the lines of:
(function ($) {
$.fn.addIncrementArrows = function (min, max, interval, fastInterval, event) {
var input = this;
/*Other building things go here*/
var timeoutDownArrow;
var intervalDownArrow;
//clicking button down for 1 second fires '-' actions
$(this).parent().children(".downarrow").mousedown(function () {
timeoutDownArrow = setTimeout(function () {
intervalDownArrow = setInterval(function () {
changeValue(-fastInterval);
//how to do event here?
}, 90);
}, 750);
}).bind("mouseup mouseleave", function () {
clearTimeout(timeoutDownArrow);
clearInterval(intervalDownArrow);
});
};
}(jQuery));
Simply what I need to declare to make it have the arrows as follows:
formnamehere.addIncrementArrows(0, 100, 1, 5, event);
If it's possible: how could I bind an action to the button within .addIncrementArrows()?
So after a bit of research I came to a conclusion:
1 - Changed the function to run inside .addIncrementArrows() as a named run-time function:
var setSliderPercentage = function (percent) {
//do stuff here
}
2 - Pass the function into the plugin as a variable name
percentageForm.addIncrementArrows(0, 100, 1, 5, setSliderPercentage);
3 - Ran the passed function within the addIncrementArrows() plugin.
$.fn.addIncrementArrows = function (min, max, interval, fastInterval, event) {
var input = this;
if (max === false) max = Infinity; //infinity and beyond!
//Other stuff here
//make the it auto increment or decrement every 100ms when 'holding down' the button after 1 second
var timeoutUpArrow;
var intervalUpArrow;
$(uparrow).mousedown(function () {
timeoutUpArrow = setTimeout(function () {
intervalUpArrow = setInterval(function () {
changeValue(fastInterval);
//
if (typeof event != "undefined") event(input.val());
//
}, 90);
}, 750);
}).bind("mouseup mouseleave", function () {
clearTimeout(timeoutUpArrow);
clearInterval(intervalUpArrow);
});
}
Related
I have a guide setup in pendo, but I need to include a function that will continue the guide when the user clicks on a different element than the target pendo element.
I found this function:
module.exports = (function wireGuideAdvance(dom, step) {
if (!step) return;
var nextStep = guide.steps[guide.getPositionOfStep(step)];
var advanceOnce = pendo._.once(pendo.onGuideAdvanced);
function checkForElementAndAdvance(e) {
var checkForNextElement = setInterval(function () {
if (dom(nextStep.elementPathRule).length) {
advanceOnce();
clearInterval(checkForNextElement);
}
}, 1000);
}
pendo.attachEvent(document, 'click', checkForElementAndAdvance);
// step wrappable method to clear all event listeners
step.after('teardown', function () {
pendo.detachEvent(document, 'click', checkForElementAndAdvance);
});
})(pendo.dom, step);
but I do not know how to use this within the Angular app.
Thank you for the previous (deleted by moderator) explanation and the simple implementation but it does not work out for me. The 'holdit' function works but it is not is not steady probably because there is an 'onmouseup' in the 'holdit' function too, Even if I disable the onmouseup at the HTML button it's not very steady. Maybe it's better to use an addEventListener- onmousedown-interval function but again I don't know how to implement it in the simplest possible way. Here's the complete function that shows a pressed button and increases the timeSeconds var by one. For safety the var. number is within a limit.
Please help.
HTML:
<img id="but4" class="button" src= "//:0" onmousedown="timesecPlus();"onmouseup="timesecPlsUp();"/>
JAVASCRIPT:
function timesecPlus() {
var pmknop = document.getElementById('but5');
pmknop.src = secminBtndwn; //inline Base64 data: button image down (pressed)
timeSeconds = ((timeSeconds>wedstrijdperiode.seconden-6)?(timeSeconds):(++timeSeconds)); //You can ++ chase-back the timeseconds until 5 sec's from period start-time
displayTime( timeSeconds );
};
function timesecPlsUp() {
var pmknop = document.getElementById('but5');
pmknop.src = secminBtn; //inline Base64 data: button image up (normal)
};
// Things I tried:
//holdit(pmknop, function () { ++timeSeconds ; displayTime( timeSeconds );}, 2000, 2);
//pmknop = pmknop.addEventListener('mousedown', function() { interval = setInterval(timesecPlus (), 2000); });
function holdit(btn, action, start, speedup) {
var t;
var repeat = function () {
action();
t = setTimeout(repeat, start);
start = start / speedup;
}
btn.onmousedown = function() {
repeat();
}
btn.onmouseup = function () {
clearTimeout(t);
}
};
The holdit function is taking four variables. The first: btn, is the button id. This is used to determine the action performed whenever the mouse is clicked.
The second variable is a reference to a function. Its called a callback function, since you will be passing a function that will be Caaalleed whenever you call holdit.
The last two variables simply determine when and how long to delay the execution of the repetition and and by how much each repetition will speed up by.
var repeat = function () {
action();
t = setTimeout(repeat, start);
start = start / speedup;
}
Repeat is a recursive function that will be called after 'start' number of milliseconds and be repeated more frequently after each iteration.
Simple implementation:
var btn = document.getElementsByClassName('button')[0];
holdit(btn, function () { timeSeconds++ ; displayTime( timeSeconds );}, 1000, 2);
Implementation without holdit:
var btn = document.getElementsByClassName('button')[0];
var couterFunc, couter=0;
btn.addEventListener('mousedown',function(){couterFunc = setInterval(update,1000); update()})
btn.addEventListener('mouseup',function(){clearInterval(couterFunc)})
/* function that will fire when button press*/
function update(){console.log(++couter)};
Since people are misunderstanding my wording, I will rewrite it, I want "with the following code below" to ignore the function which i have commented on below in my jquery if it happened in the last "X" seconds.
Here is my code.
EDIT:: Please write answers in reference to this, example. "the script ignores the change in class and the delay wont work" http://www.w3schools.com/code/tryit.asp?filename=FBC4LK96GO6H
Sorry for confusing everyone including myself.
Edited due to author's post update.
You can create custon event. By this function you will define: "delayedClick" event on the selected objects.
function delayedClickable(selector, delayTime){
$(document).ready(function(){
$(selector).each(function () {
var lastTimeFired = 0;
$(this).click(function(){
if(Date.now() - delayTime > lastTimeFired) {
lastTimeFired = Date.now();
$(this).trigger('delayedClick');
}
});
});
});
}
Remeber that you should define delayTime and this event on selected elements by:
var delayTime = 3 * 1000; // 3 sec delay between firing action
delayedClickable('.Img2', delayTime);
And then just use your event on elements. For example click event can be used in that way:
$element.on('click', function () {
// ...
});
And your custom delayedClick event should be used in that way:
$element.on('delayedEvent', function () {
// ...
});
Full example:
http://www.w3schools.com/code/tryit.asp?filename=FBC56VJ9JCA5
#UPDATE
I've found some another tricky way to keep using click function and makes it works as expected:
function delayedClickable(selector, delayTime){
$(document).ready(function(){
$(selector).each(function () {
var scope = this;
$(this).click(function(){
scope.style.pointerEvents = 'none';
setTimeout(function () {
scope.style.pointerEvents = 'auto';
}, delayTime);
});
});
});
}
And then
var delayTime = 3 * 1000; // 3 sec delay between firing action
delayedClickable('.Img2', delayTime);
That's all.
The key of second way is that we are disabling any pointer event on element when clicked and then after timeout we're turning these events back to work.
https://developer.mozilla.org/en/docs/Web/CSS/pointer-events
And full example:
http://www.w3schools.com/code/tryit.asp?filename=FBC678H21H5F
Can use setTimeout() to change a flag variable and a conditional to check flag in the event handler
var allowClick = true,
delaySeconds = 5;
$(".element1").click(function(){
if(!allowClick){
return; // do nothing and don't proceed
}
allowClick = false;
setTimeout(function(){
allowClick = true;
}, delaySeconds * 1000 );
// other element operations
})
I have a function which will take some time to run on click event.
Following is merely an example and setTimeout is there only to simulate time it may take to run it. How can I ensure when a user click on an item any previous running function(s) is(are) cancelled and only the latest onclick function is fired?
i.e. if a user clicked on it 10 times. I want to only execute the only the 10th click not the 9 clicks before.
I am hoping for a pure/vanilla js solution... NOT jQuery
(function () {
var nav = document.querySelector('.nav__toggle');
var toggleState = function (elem, one, two) {
var elem = document.querySelector(elem);
elem.setAttribute('data-state', elem.getAttribute('data-state') === one ? two : one);
};
nav.onclick = function (e) {
setTimeout(function(){
toggleState('.nav ul', 'closed', 'open');
}, 5000);
e.preventDefault();
};
})();
fiddle: http://jsfiddle.net/6p94p48m/
You need to debounce your click handler.
var button = document.getElementById("debounced");
var clickHandler = function() {
alert('click handler');
}
var debounce = function(f, debounceTimeout) {
var to;
return function() {
clearTimeout(to);
to = setTimeout(f, debounceTimeout);
}
}
button.addEventListener('click', debounce(clickHandler, 5000));
<button id="debounced" href="#">debounced</button>
Or use underscore/lodash https://lodash.com/docs#debounce
I have a setInterval on a function X that runs every 500ms. In this function X, I call another function Y that essentially binds an event on some divs. However, I would like to unbind these events the next time the function X is called (to start "fresh"). My code doesn't seem to work:
setInterval(this.board.updateBoard, 500); //called from another constructor
This then initiates the functions below:
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
for(var i = 0; i < divs.length; i++) {
$(divs[i]).unbind(); //Apparently this doesn't work?
}
//...some code here...
//find appropriate $div's (multiple of them), and then calls this.beginWalking() below on each of those
//loop here
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
return setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
};
Basically, updateBoard is called every 500ms. Each time it's called, beginWalking is called to set another interval on a div. The purpose of this other interval, which functions correctly, is to add and remove a class every 80ms. I just can't seem to unbind everything before the next updateBoard is called.
Any suggestions appreciated!
use clearInterval()
edit: $(selector).toggleClass(dir0) might also be helpful
// In other file, use a global (no var) if you need to read it from another file:
updaterGlobal = setInterval(this.board.updateBoard, 500);
// store interval references for clearing:
var updaterLocals = [];
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
// Stop existing div timers:
while(updaterLocals.length > 0){
clearInterval(updaterLocals[0]);
updaterLocals.shift(); // remove the first timer
}
//...some code here...
//loop here to call the below on several $div's
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
var interval = setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
// Save the timer:
updaterLocals.push(interval);
return;
};