结合OnMouseUp / Down功能? [英] Incorporating OnMouseUp/Down Functionality?

查看:165
本文介绍了结合OnMouseUp / Down功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个工作工具(请参阅第一个代码块),我想包括点击保存功能。

I have a working tool (see first code block), where I would like to include click-and-hold functionality.

我希望在保持左按钮时快速添加ADD,并且在右按钮被保持时快速地将其复制。就像单击功能,它已经有了,但更快的选择。

I would like to to rapidly ADD when left button is held, and rapidly SUBTRACT when right button is held. Just like the single click functionality it already has, but a faster option.

我是一个完整的新手,所以工作演示非常感谢。谢谢。

I am a complete novice, so working demos are greatly appreciated. Thank you.

代码

<!DOCTYPE html>
<html>
<head>
<script>

var Alexander = 
     {
      Strength: "AlexanderStrengthVal",
      Bonus: "AlexanderRemainingBonusVal",
      Limits: {
        Strength: { 
          max: 80,
          min: 60
        }
              }
    };

function add(character, stat)
{
  var txtNumber = document.getElementById(character[stat]);
  var newNumber = parseInt(txtNumber.value) + 1;
  if(newNumber > character.Limits[stat].max) return;
  var BonusVal = document.getElementById(character["Bonus"]);
  if(BonusVal.value == 0) return;
  var newBonus = parseInt(BonusVal.value) - 1;
  BonusVal.value = newBonus; 
  txtNumber.value = newNumber;
}

function subtract(e, character, stat)
{
  e.preventDefault();
  var txtNumber = document.getElementById(character[stat]);
  var newNumber = parseInt(txtNumber.value) - 1;
  if(newNumber < character.Limits[stat].min) return;
    var BonusVal = document.getElementById(character["Bonus"]);
  var newBonus = parseInt(BonusVal.value) + 1;
  BonusVal.value = newBonus; 
  txtNumber.value = newNumber;
}

</script>  
</head>
<body>

  <table cellpadding='5' border='1' style="text-align:center; color:#ffffff; background-color:#444444; font-family:arial; font-size:14px">
   <tr>
      <td><b>Character</b></td>
      <td><b>Strength</b></td>
      <td><b>Spending Bonus</b></td>
   </tr>
    <tr>
      <td>Alexander</td>
      <td>
        <input 
        id="AlexanderStrengthVal" 
        type="text" value="60" 
        style="width:30px; border:none; color:#ffffff; background-color:transparent; text-align:center" 
        onfocus="this.blur()" 
        onClick="add(Alexander, 'Strength')" 
        onContextMenu="subtract(event, Alexander, 'Strength');"   
        />
      </td>

      <td>
        <input 
        id="AlexanderRemainingBonusVal" 
        type="text" 
        value="30" 
        style="width:30px; border:none; color:#ffffff; background-color:transparent; text-align:center" 
        />
      </td>

    </tr>
  </table>
</body>
</html>


推荐答案

如何使用 .setTimeout() .setInterval() .onmousedown .onmouseup .onmouseout 钩子,你是否尝试过这种方法?

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 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 );
//
//
//
//

这篇关于结合OnMouseUp / Down功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆