Anup Singh
Anup Singh

Reputation: 1573

highcharts override addEvent function

in highcharts javascript file line number 1126 there is a function addEvent

/**
         * Add an event listener
         * @param {Object} el A HTML element or custom object
         * @param {String} event The event type
         * @param {Function} fn The event handler
         */
        addEvent: function (el, event, fn) {
            $(el).bind(event, fn);
        },

I want to call my custom function instead of default function, and at the same time i don't want to change highcharts.js.

I want to assign it through external function, is there any way I can achieve this??

my new code will be

addEvent: function (el, event, fn) {
    if(typeof(fn)=="string"){
        try {
            eval(fn); 
        } catch (e) {
        if (e instanceof SyntaxError) {
            console.log(e.message);
        }
        }

    }
    $(el).bind(event, fn);
}

Upvotes: 3

Views: 3467

Answers (7)

Cherif
Cherif

Reputation: 61

Use DOM events easily in a way compatible with all browsers. Here is the experience ...

Create your function, for example mouseup ...

var MeObjectDOM_mouseup = function(){
           Me blabla code....
}

Create your event now ...

if(MeObjectDOM.addEventListener){
 MeObjectDOM.addEventListener("mouseup", MeObjectDOM_mouseup ,true);
}else if(MeObjectDOM.attachEvent){
MeObjectDOM.attachEvent("mouseup", MeObjectDOM_mouseup);
}else{
 MeObjectDOM['onmouseup'] = MeObjectDOM_mouseup;
};

Your event is now compatible with IE, NETSCAPE, CHROME, EDGE, OPERA, FIREFOX, SAFARI, even older versions like Safari 5 or IE 5, 6 and Netscape 4 (^__^).

  • Chrome Mozilla it was Netscape before the recovery by Google. FireFox, and OPERA come from MOZILLA except IE and SAFARI. So your code will be compatible with all existing browsers since 1980 and before until 2019 see much more ....

Upvotes: 0

Josh Durham
Josh Durham

Reputation: 1662

Notice these lines of code in highcharts.js:

// check for a custom HighchartsAdapter defined prior to this file
var globalAdapter = win.HighchartsAdapter,
    adapter = globalAdapter || {};

// Initialize the adapter
if (globalAdapter) {
    globalAdapter.init.call(globalAdapter, pathAnim);
}


// Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object
// and all the utility functions will be null. In that case they are populated by the
// default adapters below.

Since addEvent is specified in window.HighchartsAdapter, you will need to create a custom HighchartsAdapter to override it. There is an example of a custom highcharts adapter on github.

Upvotes: 0

Jeffery To
Jeffery To

Reputation: 11936

Modifying Highcharts.addEvent with Highcharts.wrap() doesn't work because Highcharts saves an internal reference to addEvent. Changing the external Highcharts.addEvent has no effect on the internal reference.


Tracing the code backwards a bit, you'll find that addEvent comes from window.HighchartsAdapter. Highcharts can be made to work with other JavaScript frameworks by loading the appropriate adapter, which overrides the default window.HighchartsAdapter with a version that works with the particular framework.

To modify addEvent on the default adapter before Highcharts saves an internal reference, we can load the main JS file twice: (demo)

<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
    // Highcharts detects if it has been loaded more than once
    // and throws an error to alert developers
    // We work around this by unsetting the Highcharts object
    window.Highcharts = null;

    window.HighchartsAdapter.addEvent = function (el, event, fn) {
        // add your custom code here

        $(el).bind(event, fn);
    };
</script>
<script src="http://code.highcharts.com/highcharts.js"></script>

This will cause a second HTTP request to be made for the JS file, but it should return a 304 response as the browser should already have cached the file from the first request.


While this may work for now, monkey-patching someone else's code isn't the best way to proceed in the long term, e.g. you or another developer may decide to upgrade to the latest version of Highcharts (with a completely different internal API) a year from now, without realizing / remembering this change. I'd consider other ways to do what you're trying to do before resorting to monkey patching.

Upvotes: 0

stovroz
stovroz

Reputation: 7095

It's not possible to reproduce the effect of modifying the source code for addEvent at line 1126 by using the wrap utility, because for reasons I don't fully understand, the wrap is not applied to numerous internal calls made to addEvent including those triggered as a result of the events specified in the initial configuration, such as yours under plotOptions/series/point/events.

However the wrap is applied to events when added like this:

(function (H) {
    Highcharts.Chart.prototype.callbacks.push(function (chart) {
        H.addEvent(chart.container, 'click', function() { alert('click!') });
    });
}(Highcharts));

or as in your case, adding a function as a string to a point event:

(function (H) {
    Highcharts.Chart.prototype.callbacks.push(function (chart) {    
        H.addEvent(chart.series[0].data, 'click', "(function() { alert (this.y);})");
    });
}(Highcharts));

so your wrap function could deal with both of these like so:

(function (H) {
    H.wrap(H, "addEvent", function (addEvent, el, event, fn) {
        if (typeof fn == "string") {
            try {
                var evalfn = eval(fn);
                addEvent(el, event, evalfn);
            } catch (e) {
                if (e instanceof SyntaxError) {
                    console.log(e.message);
                }
            }
        } else {
            addEvent(el, event, fn);
        }
    });
})(Highcharts);

which I grant is not quite what you asked, but may offer an alternative solution for what you are trying to achieve.

Demo of all this here: http://jsfiddle.net/8wRAs/

Upvotes: 0

Paweł Fus
Paweł Fus

Reputation: 45079

Unfortuantely I don't know why wrapping addEvent doesn't work (while should!), but you can overwrite or wrap importEvents for point, to do similar thing (but only for points):

(function (H) {
    H.wrap(H.Point.prototype, 'importEvents', function () {
        if (!this.hasImportedEvents) {
            var point = this,
                options = H.merge(point.series.options.point, point.options),
                events = options.events,
                eventType;

            point.events = events;

            for (eventType in events) {
                if (typeof events[eventType] == "string") {
                    try {
                        events[eventType] = eval(events[eventType]);
                    } catch (e) {
                        if (e instanceof SyntaxError) {
                            console.log(e.message);
                        }
                    }
                }
                H.addEvent(point, eventType, events[eventType]);
                this.hasImportedEvents = true;
            }
        }
    });
}(Highcharts));

Demo: http://jsfiddle.net/cXS5u/

Upvotes: 1

Matteo Tassinari
Matteo Tassinari

Reputation: 18584

I would try this:

Highcharts.addEvent = (function(orig) {
  return function(el, event, fn) {
    if(typeof fn == "string") {
        try {
            eval(fn); 
        } catch (e) {
          if (e instanceof SyntaxError) {
            console.log(e.message);
          }
        }
    }

    orig(el, event, fn);
  };
})(Highcharts.addEvent);

using Highcharts' wrap method, this should be

(function(H) {
  H.wrap(H, "addEvent", function(addEvent, el, event, fn) {
    if(typeof fn == "string") {
      try {
        eval(fn); 
      } catch (e) {
        if (e instanceof SyntaxError) {
          console.log(e.message);
        }
      }
    }

    addEvent(el, event, fn);
  });
})(Highcharts);

Upvotes: 0

Sebastian Bochan
Sebastian Bochan

Reputation: 37588

You can overwrite this function by wrap function.

Upvotes: 0

Related Questions