0

我有一个工作工具(参见第一个代码块),我想在其中包含单击并按住功能。

我想在按住左键时快速添加,并在按住右键时快速减法。就像它已经拥有的单击功能一样,但选择更快。

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

代码:

<!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>
4

2 回答 2

1

.setTimeout()附加使用, .setInterval()to .onmousedown, .onmouseup,钩子的计时器函数怎么样.onmouseout,你尝试过这种方法吗?

或者试试我用于类似任务的准备就绪功能。小提琴

//
// #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 );
//
//
//
//
于 2013-10-16T20:27:06.173 回答
1

我会使用setIntervaland并将它们与事件clearInterval挂钩。我在这个例子中使用了jQuery正如我在其他答案之一中提到的那样,我没有在您的示例中添加代码,因为您做错了事件绑定。mousedownmouseup

我想我可能会回答这个问题,并给你一个例子,说明你应该如何将你的事件绑定到你的 DOM 并构造你的函数。

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

function add(n,val){
  var currentValue = parseInt($(n).text());
  $(n).text(currentValue+val);
}

这是一个Working demo

于 2013-10-16T21:27:24.793 回答