如何覆盖在 Prototype.js Class 中声明的 javascript 函数

how to override javascript function declared within Prototype.js Class

注意

这不是 How to override product.js file in magento as this question refers to a function used in Magento core within a Prototype Class. Additionally the question refers to a different JavaScript library, i.e. scriptaculous 和不同文件的副本。因此解决方案也不同。

正如下面最初解释的那样。更新了问题标题以使其更加清晰。


我正在开发加载 scriptaculous 库的 Magento 站点。

我想覆盖 local.js 文件中的 Autocompleter.Base 函数,它在 control.js[= 中定义52=] 与:

control.js

var Autocompleter = { };
Autocompleter.Base = Class.create({
  baseInitialize: function(element, update, options) {
    element          = $(element);
    this.element     = element;
    this.update      = $(update);
    this.hasFocus    = false;
    this.changed     = false;
    this.active      = false;
    this.index       = 0;
    this.entryCount  = 0;
    this.oldElementValue = this.element.value;

    if(this.setOptions)
      this.setOptions(options);
    else
      this.options = options || { };

    this.options.paramName    = this.options.paramName || this.element.name;
    this.options.tokens       = this.options.tokens || [];
    this.options.frequency    = this.options.frequency || 0.4;
    this.options.minChars     = this.options.minChars || 1;
    this.options.onShow       = this.options.onShow ||
      function(element, update){
        if(!update.style.position || update.style.position=='absolute') {
          update.style.position = 'absolute';
          Position.clone(element, update, {
            setHeight: false,
            offsetTop: element.offsetHeight
          });
        }
        Effect.Appear(update,{duration:0.15});
      };
    this.options.onHide = this.options.onHide ||
      function(element, update){ new Effect.Fade(update,{duration:0.15}) };

    if(typeof(this.options.tokens) == 'string')
      this.options.tokens = new Array(this.options.tokens);
    // Force carriage returns as token delimiters anyway
    if (!this.options.tokens.include('\n'))
      this.options.tokens.push('\n');

    this.observer = null;

    this.element.setAttribute('autocomplete','off');

    Element.hide(this.update);

    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
    Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
  },

当它来自 Prototype Class 时,我该如何覆盖它?

我可以覆盖它调用的覆盖 Effect.Fade class,但这不是 Prototype Class.

effect.js

Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
    from: element.getOpacity() || 1.0,
    to:   0.0,
    afterFinishInternal: function(effect) {
      if (effect.options.to!=0) return;
      effect.element.hide().setStyle({opacity: oldOpacity});
    }
  }, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

到目前为止的尝试次数:

local.js

// WORKS
Effect.Fade = function(element) {
    element = $(element);
    var oldOpacity = element.getInlineOpacity();
    var options = Object.extend({
        from: element.getOpacity() || 1.0,
        to:   0.0,
        afterFinishInternal: function(effect) {
            if (effect.options.to!=0) return;
            effect.element.hide().setStyle({opacity: oldOpacity});
        }
    }, arguments[1] || { });
    return new Effect.Opacity(element,options);
};

// DOES NOT WORK
Autocompleter.Base.baseInitialize = function(element, update, options) {
    element          = $(element);
    this.element     = element;
    this.update      = $(update);
    this.hasFocus    = false;
    this.changed     = false;
    this.active      = false;
    this.index       = 0;
    this.entryCount  = 0;
    this.oldElementValue = this.element.value;

    if(this.setOptions)
        this.setOptions(options);
    else
        this.options = options || { };

    this.options.paramName    = this.options.paramName || this.element.name;
    this.options.tokens       = this.options.tokens || [];
    this.options.frequency    = this.options.frequency || 0.4;
    this.options.minChars     = this.options.minChars || 1;
    this.options.onShow       = this.options.onShow ||
        function(element, update){
            if(!update.style.position || update.style.position=='absolute') {
                update.style.position = 'absolute';
                Position.clone(element, update, {
                    setHeight: false,
                    offsetTop: element.offsetHeight
                });
            }
            Effect.Appear(update,{duration:0.15});
        };
    debugger;
    this.options.onHide = this.options.onHide ||
        function(element, update){ new Effect.Fade(update,{duration:0.15}) };

    if(typeof(this.options.tokens) == 'string')
        this.options.tokens = new Array(this.options.tokens);
    // Force carriage returns as token delimiters anyway
    if (!this.options.tokens.include('\n'))
        this.options.tokens.push('\n');

    this.observer = null;

    this.element.setAttribute('autocomplete','off');

    Element.hide(this.update);

    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
    Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
};

而不是:

Autocompleter.Base.baseInitialize = function(element, update, options) {

尝试:

Autocompleter.Base.prototype.baseInitialize = function(element, update, options) {

运行下面的演示。

var Autocompleter = { };
Autocompleter.Base = Class.create({
  baseInitialize: function(element, update, options) {
    console.log("I'm original baseInitialize")
  }
});

new Autocompleter.Base().baseInitialize();

Autocompleter.Base.prototype.baseInitialize = function () { console.log("I'm modified baseInitialize"); }

new Autocompleter.Base().baseInitialize();
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.js"></script>