Incorporating Onmouseup/down Functionality?
I have a working tool (see first code block), where I would like to include click-and-hold functionality. I would like to to rapidly ADD when left button is held, and rapidly SUBTR
Solution 1:
How about attaching timer functions that use .setTimeout()
, .setInterval()
to .onmousedown
, .onmouseup
, .onmouseout
hooks, have you tried that approach?
Or try this ready to go function I use for similar tasks. fiddle.
//// #Timer//// if you are unfamiliar with this code construct,// ( I think it is called 'module' pattern IIRC )// this is base structure behind it://// defines/runs/sets_context/passes_arguments of anonymous function in one go// makes 'safe' ( private ) scope for module definition// module assignment is performed at the top// where it is easy to spot, rename, and shift around where needed// 'factory' is a function that is supposed to return whatever the 'module' is// be it a function, object, or whatever,// and to assign it to arbitrary 'host' object,// providing room to rename it in case of naming collisions//// ;(( function ( name, factory ) {//// // this === module's context//// this[name] = factory();//// } ).call(//// hostObject, // object to attach module to// "customModuleName", // arbitrary name to use for it// function () { // factory method that is supposed to define/return ( preferably independent ) piece of functionality//// // save to do whatever is required in this scope// // without the impact on globals.// // declare identifiers, etc.// // whatever this function returns is assigned to context above//// function doStuff () {// return Math.random() > .5;// }//// var// _api =// {// props : 1,// methods : function () {// var stuff;// stuff = doStuff();// return stuff;// }// };//// // ...code//// // and return whatever the module's goal is// return _api;//// }//// ));//
;(( function ( field, dfn ) {
// add 'Timer' identifier to global scopethis[field] = dfn();
} ).call(
window, // object to asign function to"Timer", // property name to usefunction () {
// helpers and// shortcuts for use by code bellowvar undef; // === undefinedvar aproto = Array.prototype;
var _ = {
// used to filter functions in timer api arguments
isfn : function ( o ) {
returntypeof o == "function";
},
// is provided parameter an object
isobj : function ( o ) {
return o === Object( o );
},
// checks provided parameter,// returns false for: null, undefined, NaN// used to check if parameter is passed to timer methods
isvalid : function ( o ) {
return ( o != null ) && ( o === o );
},
// removes array elements that match passed arguments// supposed to be used through .call/.apply function method:// _.gc.call( arr, "a", "b", "c" ), etc.// iterates array backward, '.splice-ing' it by 1 if current value// matches one of provided arguments// returns gc-ed array// used by .off() method to remove scheduled function(s)
gc : function () {
// this === ( array ) target_array_to_cleanup// provided arguments[] to removevar togc = _.slice( arguments );
for (
var i = this.length;
--i >= 0;
( togc.indexOf( this[i] ) != -1 )
&& this.splice( i, 1 )
);
returnthis;
},
// empties passed array and returns it// used by .off() method to remove scheduled functions
empty : function ( arr ) {
return ( arr.length = 0, arr );
},
// loops array// uses native .forEach if available// otherwise simulates the behaviour// returns iterated array// used by .fire() method to loop through registered function[] and// to execute them in order
arreach : ( function () {
return ( typeof aproto.forEach == "function" )
? function ( arr, fn ) {
arr.forEach( fn );
return arr;
}
: function ( arr, fn ) {
for (
var i = 0,
l = arr.length;
i < l;
( i in arr )
&& fn.call( this, arr[i], i, arr ),
i++
);
return arr;
};
} )(),
// substitues content of array ( arr )// with provided array's content ( arrnew )// returns modified array ( arr )// used by .start() method to quickly switch timer handler arguments// if any are passed to it
arrsub : function ( arr, arrnew ) {
return ( aproto.push.apply( _.empty( arr ), arrnew ), arr );
},
// loops own properies of an object and retuns it// used by .off() method, ant _.init() function// to perform appropriate tasks ( object cleanup/property_assignment )
owneach : function ( obj, fn ) {
for (
var l in obj
) {
_.owns( obj, l )
&& fn.call( obj, l, obj[l] );
}
return obj;
},
// asyns a function// returns new function based on provided one// that will run asyncrounously// used to async 'tick' handlersasync : function ( fn ) {
returnfunction () {
var host = this;
var args = _.slice( arguments );
var origfn = fn;
setTimeout(
function () {
origfn.apply( host, args );
}
);
returnthis;
};
},
// asigns properties of an object ( propsObj )// to provided ( obj ) object// used in couple of places to quickly assign properties/values to objects
init : function ( obj, propsObj ) {
_.owneach(
propsObj,
function ( field, value ) {
obj[field] = value;
}
);
return obj;
},
// core {}.hasOwnProperty shortcut
owns : function ( obj, field ) {
returnObject( obj ).hasOwnProperty( field );
},
// native [].slice shortcut// used to turn dynamic arguments[] to real array
slice : function ( args, m, n ) {
return aproto.slice.call( args, m, n );
},
// empties an object// used by .off() method to empty evHandler functions cache
vacate : function ( obj ) {
for (
var l in obj
) {
try {
_.owns( Object.prototype, l )
|| ( delete obj[l] );
} catch( xc ) {}
}
return obj;
}
};
// main function uses this strings// for subscribing/removing/executing handlersvar timerEvent = {
start : "tickStart",
stop : "tickStop",
tick : "tick",
end : "tickEnd"
};
return (function ( listener ) {
// main timer function// @param1, float, optional, how often to fire 'tick' events, default == 1000, ( == 1sec )// @param2, integer, optional, how many times to fire 'tick' event, default == Infinity// returns, Object, object with following api://// registering functions for 'timerEvent' events://// .on( evType, func )// # caches a function for given event type ( of 'timerEvent' object )// .off( [ evType, func] )// # unregisteres function for given event type// # if no function is provided removes all functions registered for event 'evType'// # if nothing is provided removes all registered functions// .fire( evType [, ...params_for_registered_handlers ] )// # runs functions registered for given event type// # passing provided arguments to them, if any// # used internaly when .start() method is called//// these are for controling timer object://// .start([ ...params])// # starts triggering 'tick' events updating internal state// # passes provided parameters to triggerd functions,// # ( available through .data property of object passed to handlers )// .stop()// # pauses triggering 'tick' events ( if Timer object is in 'running state' )// # triggers 'tickStop' event// .reset()// # nulls internal state, stops dispatching 'ticks', resets counter// # triggers 'tickEnd' event//// these are for quering internal timer state://// .currentCount()// # how many times Timer fired so far// # returns, integer// .delay()// # gives timer's delay// # returns, float// .repeatCount()// # how many times timer will dispatch 'tick' events// # returns, integer// .running()// # 'is running' state// # returns, boolean//returnfunction ( delay, fireCount ) {
return (function ( delay, fireCount ) {
// preconfigured object that will handle 'tick' eventsvar host = this;
// timer object's internal state// used/updated by timervar timerState =
{
currentCount : 0,
delay : Math.abs( parseFloat(delay) ) || 1000,
repeatCount : Math.abs( parseInt(fireCount) ) || Infinity,
running : false,
interval : undef
};
// hack to reset .currentCount property asynchronously in .reset() method// without using it this way, ( by zeroing it directly, like: timerState.currentCount = 0 )// will make last 'tick' function call report: .currentCount() == 0,// instead of whatever the currentCount was// at the time the 'last tick' dispatch was performed//// because the handlers are runned asyncronously, and// because setting currentCount to 0 manualy ( synchronously )// will reset it before last function gets to be runned// reseting it asyncronously schedules a function to reset a property// making 'last tick' function report correct currentCount ( not 0 ).var zer0CurrentCount =
_.async(
function () {
timerState.currentCount = 0;
}
);
// holds arguments passed to last .start() call// uses these for further .start() calls if no new arguments are given// passes them to triggered functionsvar fireargs = [];
// attaches timer api// ( .start, .stop, .reset, .currentCount, .delay, .repeatCount, .running )// to timer object
_.init(
host,
{
// handles starting event dispatch// if arguments are given, caches and// uses them for further calls// 'keeps an eye' on timer's configuration options// updating/aborting dispatch when/if necessary// triggering corresponding events and functions// does nothing if timer is already in 'active' statestart: function () {
var startargs;
host.running()
|| (
timerState.running = true,
( startargs = _.slice( arguments ) ).length
&& _.arrsub( fireargs, startargs ),
host.fire.apply(
host,
[timerEvent.start]
.concat( fireargs )
),
timerState.currentCount += 1,
host.fire.apply(
host,
[timerEvent.tick]
.concat( fireargs )
),
( timerState.currentCount == timerState.repeatCount )
&& host.reset()
|| (
timerState.interval =
setInterval(
function () {
timerState.currentCount += 1;
host.fire.apply(
host,
[timerEvent.tick]
.concat( fireargs )
);
( timerState.currentCount >= timerState.repeatCount )
&& host.reset();
},
timerState.delay
)
)
);
return host;
},
// pauses running functions ( if timer{} is in 'running' state )// fires 'tickStop' event// passes arguments ( given in .start call ) to cached functions// updates timer's internal statestop: function () {
host.running()
&& (
( timerState.interval !== undef )
&& (
clearInterval( timerState.interval ),
timerState.interval = undef
),
timerState.running = false,
host.fire.apply(
host,
[timerEvent.stop]
.concat(fireargs)
)
);
return host;
},
// cancels event dispatch// nulls internal state// fires 'tickEnd' functionsreset: function () {
( timerState.interval !== undef )
&& (
clearInterval( timerState.interval ),
timerState.interval = undef
);
timerState.running = false;
host.fire.apply(
host,
[timerEvent.end]
.concat( fireargs )
);
zer0CurrentCount();
return host;
},
// query timer's current state:currentCount: function () {
return timerState.currentCount;
},
delay: function () {
return timerState.delay;
},
repeatCount: function () {
return timerState.repeatCount;
},
running: function () {
return timerState.running;
}
}
);
return host;
}).call( listener( {} ), delay, fireCount );
}
})(
// function to configure an object to handle custom events// gives basic event handling functionality to provided object// attaches .on/.off/.fire methods to it,// used by main Timer function// ( to generate base objects for handling timer events )// passed as single ( private ) argument to code abovefunction ( obj ) {
if (
_.isobj(obj)
) {
// evHandler parameter object is used to store provided handlers in
(function ( evHandlers ) {
// plain object to configure for custom event handlingvar host = this;
// attaches api ( .on, .off, .fire ) to provided object
_.init(
host,
{
// if function is provided cache it in 'evHandlers' object// ( to be called when needed )// both, event type and function argument, are requiredon: function ( evtype, fn ) {
if (
_.isvalid( evtype )
&& _.isfn( fn )
) {
_.owns( evHandlers, evtype )
&& evHandlers[evtype].push( fn )
|| ( evHandlers[evtype] = [fn] );
}
return host;
},
// deletes a function ( registered for evtype ) from evHandlers{}// both parameters are optionaloff: function ( evtype, fn ) {
if (
_.isvalid( evtype )
) {
if (
_.owns( evHandlers, evtype )
) {
_.isfn( fn )
&& (
_.gc.call( evHandlers[evtype], fn ),
evHandlers[evtype].length
|| ( delete evHandlers[evtype] ), 1
)
|| (
_.empty( evHandlers[evtype] ),
delete evHandlers[evtype]
);
}
} else {
_.owneach(
evHandlers,
function ( evtype, fns ) {
_.empty( fns );
}
);
_.vacate( evHandlers );
}
return host;
},
// triggers functions registered for ( string ) evtype event// passes 'event{}' to handlers// it holds event type ( .type ),// data[] ( .data ) provided through .fire call,// object through which method is called ( .target )// and current execting function ( .handler )// runs handlers asynchronusly by passing them to// _.async() method before executionfire: function ( evtype ) { // ( any )...argsif (
_.isvalid( evtype )
) {
if (
_.owns( evHandlers, evtype )
) {
var fireargs = _.slice( arguments, 1 );
_.arreach(
evHandlers[evtype],
function ( evhandler ) {
_.async( evhandler ).call(
host,
{
type : evtype,
data : fireargs,
target : host,
handler : evhandler
}
);
}
);
}
}
return host;
}
}
);
}).call(
obj, // passed object to apply event handling functionality to
{} // plain object to cache registered functions in
);
}
// gives back passed/configued objectreturn obj;
}
);
}
));
//// use://// set event dispatch frequency 2x/sec// run it 5x ( skip second argument to run functions indefinitely )// check out the consolevar timerObj = Timer( 1000 / 2, 5 );
// shortcut function to start the timerfunctiongoTimer () {
// start 'ticking' functions,// pass arbitrary arguments to handlers
timerObj.start(
Math.random(),
( newDate ).valueOf()
);
}
// register functions for 'tick' cycle
timerObj
.on(
"tickStart",
function ( e ) {
console.clear();
console.log(
e.type + ", \n",
( newDate ).valueOf()
);
}
)
.on(
"tick",
function ( e ) {
// updateStuff();console.log(
e.type + "#1, "
, "#", this.currentCount(),", "
, e.data
);
}
)
.on(
"tick",
function ( e ) {
// updateStuff();console.log(
e.type + "#2, "
, "Math.random() < Math.random(): "
, Math.random() < Math.random()
);
}
)
.on(
"tickEnd",
function ( e ) {
console.log(
e.type + ", \n"
, "e.target === this: "
, e.target === this
, ", e.target === timerObj: "
, e.target === timerObj
, "."
);
setTimeout( goTimer, 10000 * Math.random() );
}
);
//setTimeout( goTimer, 2000 );
////////
Solution 2:
I'd use setInterval
and clearInterval
and hook them on mousedown
and mouseup
events. I am using jQuery for this example. I am not adding code to your example, because you are doing the event binding wrong, as I mentioned in one of my other answers.
I thought I might answer this question and also give you an example on how you should bind your events to your DOM and structure your functions.
var mouseDown;
jQuery(document).ready(function($){
$('#number').on('mousedown',function(e){
mouseDown = setInterval(add,150,this,1); // 150 is the number of ms you want// to delay each number addition
})
.on('mouseup',function(e){
clearInterval(mouseDown);
});
});
functionadd(n,val){
var currentValue = parseInt($(n).text());
$(n).text(currentValue+val);
}
Here's a Working demo
Post a Comment for "Incorporating Onmouseup/down Functionality?"