[BUG] iOS click event issue and instanceof failing

I have a runtime that adds charts to multiple canvases on the same page. I have a list of charts in the left column, and every time one of those items are clicked, I add a chart on the right column. I am using Vaadin in my runtime stack.

On iOS, after I add a chart, the Vaadin stack no longer receives any click events.

So I set events=[] hoping that would solve the problem. It did not.

So instead of adding canvas, I added iframes, then added canvas to the iframes, and fed that canvas to Charts.js, in hopes of isolating the click eater.

Charts.js would not accept the canvas or it’s context2d because BOTH of the instanceof checks in platform.dom.js. fail when the canvas is coming from the iframe. When I remove the type checks, Charts.js works like a charm.

	return {
		acquireContext: function(item, config) {
			if (typeof item === 'string') {
				item = document.getElementById(item);
			} else if (item.length) {
				// Support for array based queries (such as jQuery)
				item = item[0];
			}

			if (item && item.canvas) {
				// Support for any object associated to a canvas (including a context2d)
				item = item.canvas;
			}

			if (item instanceof HTMLCanvasElement) {
				// To prevent canvas fingerprinting, some add-ons undefine the getContext
				// method, for example: https://github.com/kkapsner/CanvasBlocker
				// https://github.com/chartjs/Chart.js/issues/2807
				var context = item.getContext && item.getContext('2d');
				if (context instanceof CanvasRenderingContext2D) {
					initCanvas(item, config);
					return context;
				}
			}

			return null;
		}

Environment

  • Chart.js version: 2.5
  • Browser name and version: iOS safari and chrome
  • Link to your project: n/a

Author: Fantashit

1 thought on “[BUG] iOS click event issue and instanceof failing

  1. Your else if condition includes the first one and doesn’t really mean: “the canvas is in an IFRAME” but “item is not a HTMLCanvasElement because ????”. And there are more reliable ways to detect that the canvas is contained in IFRAME (e.g. canvas.ownerDocument !== document), so basically your code could be written like that:

        var context = item && item.getContext && item.getContext('2d');
        if (context) {
            config._isInIframe = item.ownerDocument !== document;
            initCanvas(item, config);
            return context;
        }

    But handling canvas in IFRAME should not become a special case across the code so I would not add this extra config._isInIframe until we really need it. Also removing the two instanceof can help to fix #3696 and #3887 🙂

Comments are closed.