어떻게 그 방법을 시도, 타이머 .setTimeout()
사용하는 함수, .setInterval()
.onmousedown
에, .onmouseup
, .onmouseout
후크를 부착 어떻습니까?
또는 이와 비슷한 작업을 수행 할 준비가되었습니다. 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 scope
this[field] = dfn();
}).call(
window, // object to asign function to
"Timer", // property name to use
function() {
// helpers and
// shortcuts for use by code bellow
var undef; // === undefined
var aproto = Array.prototype;
var _ = {
// used to filter functions in timer api arguments
isfn : function (o) {
return typeof 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 remove
var togc = _.slice(arguments);
for (
var i = this.length;
--i >= 0;
(togc.indexOf(this[i]) != -1)
&& this.splice(i, 1)
);
return this;
},
// 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' handlers
async : function (fn) {
return function() {
var host = this;
var args = _.slice(arguments);
var origfn = fn;
setTimeout(
function() {
origfn.apply(host, args);
}
);
return this;
};
},
// 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) {
return Object(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 handlers
var 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
//
return function (delay, fireCount) {
return (function (delay, fireCount) {
// preconfigured object that will handle 'tick' events
var host = this;
// timer object's internal state
// used/updated by timer
var 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 functions
var 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' state
start: 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 state
stop: 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' functions
reset: 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 above
function (obj) {
if (
_.isobj(obj)
) {
// evHandler parameter object is used to store provided handlers in
(function (evHandlers) {
// plain object to configure for custom event handling
var 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 required
on: 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 optional
off: 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 execution
fire: function (evtype) { // (any)...args
if (
_.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 object
return obj;
}
);
}
));
//
// use:
//
// set event dispatch frequency 2x/sec
// run it 5x (skip second argument to run functions indefinitely)
// check out the console
var timerObj = Timer(1000/2, 5);
// shortcut function to start the timer
function goTimer() {
// start 'ticking' functions,
// pass arbitrary arguments to handlers
timerObj.start(
Math.random(),
(new Date).valueOf()
);
}
// register functions for 'tick' cycle
timerObj
.on(
"tickStart",
function (e) {
console.clear();
console.log(
e.type + ", \n",
(new Date).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);
//
//
//
//
함께 코드의 다른 비트를 볼트 노력의 문제입니다! 클릭 및 보류 기능으로 무엇을하려고하는지 정확히 모르겠지만 이론적으로 버튼 대신 문서에 핸들러를 할당 할 수 있어야합니다. –
발견 한 코드는 버튼이 없으면 작동하지 않습니다. 버튼없이 마우스 이벤트를 조사해야합니다 ... http://www.w3schools.com/jsref/event_onmousedown.asp를보고 어떤 버튼이 눌러 졌는지 탐지하는 예제를 확인하십시오. –