Javascript 扩展库时追加jQuery回调函数

Javascript 扩展库时追加jQuery回调函数,javascript,jquery,callback,Javascript,Jquery,Callback,简短版本:我正在扩展一个jQuery对象函数,该函数用于获取0-3个参数,并将它们作为第二个到第四个参数传递到jQuery.animate。除此之外,我想隔离回调并在它的末尾放入另一个函数调用 我通过jQuery.fn.newfunction=…以普通方式扩展jQuery库。这是一个自定义动画功能,特别是一个扩展对象的功能,使其外部宽度(包括边距)等于其父节点的内部宽度 jQuery.fn.expand_to_parent_container = function() { var args

简短版本:我正在扩展一个jQuery对象函数,该函数用于获取0-3个参数,并将它们作为第二个到第四个参数传递到
jQuery.animate
。除此之外,我想隔离回调并在它的末尾放入另一个函数调用


我通过
jQuery.fn.newfunction=…
以普通方式扩展jQuery库。这是一个自定义动画功能,特别是一个扩展对象的功能,使其外部宽度(包括边距)等于其父节点的内部宽度

jQuery.fn.expand_to_parent_container = function() {
  var args = Array.prototype.slice.call(arguments);

  return this.each(function(){
    var parent = $(this).parent();
    parent.inner_width = parent.innerWidth();

    var inner_outer_differential = $(this).outerWidth(true) - $(this).width();

    // store original width for reversion later
    $(this).data('original_width', $(this).width());

    args.unshift({ width: parent.inner_width - inner_outer_differential });

    $.fn.animate.apply($(this), args );
  });
}
很简单。我正在使用
参数
局部变量,将其转换为数组,并取消移动第一个参数,它将进入
.animate
()的
属性
槽中。因此,其目的是允许
.expand\u to\u parent\u container
接受参数
duration,easing,callback
,使用通常的jQuery约定,使它们在直观模式中成为可选的(例如,如果只传递了一个函数,它将成为回调)。看起来好像是
jQuery.speed
负责解决这个问题,但我不想直接使用它/篡改它,因为它不像其他jQuery函数那样具有公共性/不受欢迎性,而且我宁愿将任务委托给
.animate

这是我的回归函数

jQuery.fn.contract_to_original_size = function() {
  var args = Array.prototype.slice.call(arguments);

  var callback_with_width_reset = function(){
    callback();
    $(this).width('auto');
  }

  args.unshift({ width: $(this).data('original_width') });

  if($(this).data('original_width')) {
    $.fn.animate.apply($(this), args );
  } else {
    $(this).width('auto');
  }
}

我在
var callback\u with\u width\u reset…
赋值中明确了我想要的行为,因为我希望将width属性重置为auto,以便将其恢复到更接近其原始状态,并从大量动画过程中可能发生的任何疯狂状态中恢复。但是,我不知道如何从
参数
参数
中分出回调函数。我目前的解决方案是,除非出现更好的解决方案,否则我将采用以下解决方案:

var arguments_length = arguments.length;
for(var i = 0; i < arguments_length; i++) {
  if(typeof arguments[i] == 'function') {
    var temp = arguments[i];
    arguments[i] = function(){
      temp();
      $(this).width('auto');
    }
  }
}
var arguments\u length=arguments.length;
对于(变量i=0;i
在相关的huh时刻,
Array.prototype.slice.call(参数)的返回值似乎没有按预期工作。最初,我没有遍历
参数,而是将原型调用设置为分配给
args
,然后通过
对(args中的arg)
进行迭代。但有很多意想不到的行为。我想现在别提了

这似乎是可行的,但它有两个缺点,似乎并不重要,但仍然感觉不对

  • 它在检测哪一个参数是回调函数方面相对“愚蠢”
  • 我对参数[i]
  • 的重置在很大程度上取决于不带参数的函数。幸运的是,
    .animate
    中的回调函数确实不带任何参数,因此现在它不是什么大问题,但我怀疑更灵活的扩展将更智能地处理这个问题
    有几件事我想很快指出:

    • 如果一次在多个对象上调用
      expand\u to\u parent\u container
      ,则会将
      {width:…}
      对象取消移动到
      args
      中,并且永远不会将其移回
    • contract\u to\u original\u size
      不使用
      this。each()
      也不会
      返回此
      ,并且反复取消移动宽度对象也会遇到同样的问题
    • 您可以确保您的代码仅设置
      原始宽度
      (如果尚未设置),在此处停止您的一个问题(在展开时开始展开/任何不会弄乱它的东西!)
    • 如果仍然需要,您可以在arguments数组上使用它来非常轻松地检测和替换回调函数
    下面是稍作调整的代码:

    jQuery.fn.expand_to_parent_container = function() {
      // instead of Array.prototype, we can grab slice from an empty array []
      var args = [].slice.call(arguments);
    
      return this.each(function(){
        var parent = $(this).parent();
        parent.inner_width = parent.innerWidth();
    
        var inner_outer_differential = $(this).outerWidth(true) - $(this).width();
        // store original width for reversion later
        if (!$(this).data('original_width'))
        {
          $(this).data('original_width', $(this).width());      
        }
    
        args.unshift({ width: parent.inner_width - inner_outer_differential });
        $.fn.animate.apply($(this), args );
        args.shift(); // push the width object back off in case we have multiples
      });
    }
    
    jQuery.fn.contract_to_original_size = function() {
      var args = Array.prototype.slice.call(arguments);
      var callback;
    
      var callback_with_width_reset = function(){
        if (callback) callback.apply(this,arguments);
        // do something else like:
        // $(this).width('auto');
        // you may want to $(this).data('original-width', null); here as well?
      }
    
      args = $.map(args, function(param) {
        // if the parameter is a function, replace it with our callback
        if ($.isFunction(param)) {
          // and save the original callback to be called.
          callback = param;
          return callback_with_width_reset;
        }
        // don't change the other params
        return param;
      });
    
      // we didn't find a callback already in the arguments
      if (!callback) { 
        args.push(callback_with_width_reset);
      }
    
    
      return this.each(function() {
        // rather than shift() the new value off after each loop
        // this is another technique you could use:
    
        // create another copy so we can mess with it and keep our template
        var localArgs = [].slice.call(args); 
        // also - storing $(this) is going to save a few function calls here:
        var $this = $(this);
    
        if($this.data('original_width')) {
          localArgs.unshift({ width: $this.data('original_width') });
          $.fn.animate.apply($this, localArgs );
        } else {
          $this.width('auto');
        }    
      });
    }
    

    +1认识到在道路上扰乱速度可能是不好的。如果你决定打破它,你不会是第一个,事实上jQueryUI1.8已经打破了它。你的问题的第2部分很容易解决:
    temp.apply(这个,参数)
    而不是
    temp()
    Lovely。谢谢你抽出时间。这非常有效,我从您的优秀代码中学到了一些非常有用的协商变量范围的实践。我最终删除了shift-unshift方法,因为它感觉不如localArgs方法直观。我还添加了一个检查器,这样,如果当前宽度已经等于目标宽度,则不会调用
    .animate