Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rtl regresssions in v3 - The sequel #9324

Closed
danielgindi opened this issue Jun 27, 2021 · 7 comments · Fixed by #9340 or #9353
Closed

Rtl regresssions in v3 - The sequel #9324

danielgindi opened this issue Jun 27, 2021 · 7 comments · Fixed by #9340 or #9353

Comments

@danielgindi
Copy link
Contributor

This is the sequel to #9194

Expected Behavior

rtl: true in legend with onClick event handlers should hit test the correct label position

Current Behavior

It hit tests the opposite label

Possible Solution

Find the missing piece. Some function out there does not use the rtl helper

Steps to Reproduce

https://codepen.io/danielgindi/pen/rNmBKzP

Context

#9194

Environment

  • Chart.js version: 3.4.0
  • Chrome 91.0.4472.77
@danielgindi
Copy link
Contributor Author

danielgindi commented Jun 27, 2021

@etimberg etimberg added this to the Version 3.4.1 milestone Jun 27, 2021
@etimberg
Copy link
Member

I believe that's the right spot to edit for this fix. Similarly, line 258 should be verified as well

@etimberg
Copy link
Member

etimberg commented Jul 1, 2021

hitboxes

I'm looking into this. It looks like the labels are drawn 3, 2, 1 but the hitboxes are drawn 1, 2, 3. I'm not exactly sure why yet, but making progress.

@etimberg
Copy link
Member

etimberg commented Jul 1, 2021

Ok, made some progress. During draw we implicitly reverse the positions to draw each row from right to left. This isn't really a problem, however in the hit test code we assume that hitboxes[i] corresponds to legendItems[i] but this isn't the case.

I think a solution here would be to update the order of the hitboxes during draw so that this case is true. Longer term, I think we need to redo the data model of the legend so that all of the RTL handling occurs during fit and the draw becomes a very simple loop. At the same time, we could simplify the internal state such that there is only a single array rather than two arrays that have to be kept in sync. This change is likely breaking so would need to wait for V4.

@kurkle thoughts?

@danielgindi
Copy link
Contributor Author

@etimberg note that in v2 there was a single loop which generated a single array of positions

@danielgindi
Copy link
Contributor Author

@etimberg almost there!
The ordering of the hitboxes is now correct, but their widths are inverted.
So if you have

[-----4-------] [--3--] [--------------2-------------] [-----1-----]

it will hit like this:

[-----4-----] [--------------3-------------] [--2--] [-----1-------]

@etimberg etimberg reopened this Jul 4, 2021
@etimberg etimberg modified the milestones: Version 3.4.1, Version 3.5.0 Jul 4, 2021
@danielgindi
Copy link
Contributor Author

@etimberg

Correct rtl version:

  adjustHitBoxes() {
    const me = this;
    if (!me.options.display) {
      return;
    }
    const titleHeight = me._computeTitleHeight();
    const {legendHitBoxes: hitboxes, options: {align, labels: {padding}, rtl}} = me;
    const rtlHelper = getRtlAdapter(rtl, me.left, me.width);
    if (this.isHorizontal()) {
      let row = 0;
      let left = _alignStartEnd(align, me.left + padding, me.right - me.lineWidths[row]);
      for (const hitbox of hitboxes) {
        if (row !== hitbox.row) {
          row = hitbox.row;
          left = _alignStartEnd(align, me.left + padding, me.right - me.lineWidths[row]);
        }
        hitbox.top += me.top + titleHeight + padding;
        hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);
        left += hitbox.width + padding;
      }
    } else {
      let col = 0;
      let top = _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height);
      for (const hitbox of hitboxes) {
        if (hitbox.col !== col) {
          col = hitbox.col;
          top = _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height);
        }
        hitbox.top = top;
        hitbox.left += me.left + padding;
        hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);
        top += hitbox.height + padding;
      }
    }
  }

No rtl conditioning, just pass through the rtl helper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants