Skip to content
This repository has been archived by the owner on Mar 9, 2023. It is now read-only.

Flesh out the web editor, remove drag-and-drop #258

Merged
merged 5 commits into from
Nov 5, 2022

Conversation

dabreegster
Copy link
Contributor

screencast.mp4

Remove drag-and-drop for now, since it complicates the code, we were using a library I'm not sure is the right choice, and the UX of dragging a trash can to a lane vs a lane to a trash can is a bit unclear to me. Instead, just have some buttons inline to each card, and add new lanes to the end always.

this.originalTags = tags;

// Remove these immediately. If they're rendered invisibly, they mess up indices.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still temporary. Seeing the center line where direction changes would be quite helpful visually.

(lane) => lane.type != "separator"
);

// All of the state is immutable, except for road. The source of truth for
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different -- and simpler -- than before, when the source of truth was the sortable cards in the DOM. Anytime we make a mutation, we just re-render all of the cards from scratch. This is cheap enough.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplicity gained by this approach is a huge win in my experience.

};

document.getElementById("new-driving").onclick = () => {
this.road.lanes.push({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always appending to the end is clunky. You had suggested having + buttons in between each pair of lanes, and presumbly a way to click the type and change it. I like that idea now that I type it out; I'll try that in a followup

@github-actions
Copy link

github-actions bot commented Nov 2, 2022

Benchmark for bf8158e

Click to view benchmark
Test Base PR %
tests/224637155 5.5±0.02µs 5.4±0.00µs -1.82%
tests/380103730 Japanese Expressway 7.1±0.09µs 7.1±0.03µs 0.00%
tests/389654080 9.0±0.01µs 8.9±0.01µs -1.11%
tests/49207928 cycleway:BACKWARD=lane 6.6±0.02µs 6.6±0.01µs 0.00%
tests/8591383 a bidirectional cycleway, oneway:bicycle 7.5±0.02µs 7.4±0.01µs -1.33%
tests/bus:lanes=designated| 6.8±0.02µs 6.8±0.03µs 0.00%
tests/busway=lane 6.3±0.01µs 6.2±0.00µs -1.59%
tests/cycleway=lane 6.4±0.01µs 6.3±0.07µs -1.56%
tests/cycleway=opposite oneway=yes oneway:bicycle=no 6.0±0.17µs 6.0±0.01µs 0.00%
tests/cycleway=opposite_track oneway=yes, deprecated 7.0±0.01µs 7.0±0.01µs 0.00%
tests/sidewalk:right=yes 5.6±0.02µs 5.6±0.01µs 0.00%
tests/sidewalk=both 5.8±0.02µs 5.8±0.01µs 0.00%

@Robinlovelace
Copy link

This looks as easy to user as streetmix.net, if not more so. And it's simpler which is good (and more relevant to OSM). Transport focused OSM editing functionality here we come?

@michaelkirk
Copy link
Contributor

Sorry I haven't been following development here that closely, so feel free to ignore me if I'm off base.

I felt pretty good about the UI we iterated on for the abstreet lane editor, where you could drag-and-drop lanes to re-order them, but deleting was a click-button action.

Maybe that's a reasonable route to work towards for this web implementation:

dragon.mov.mp4

@dabreegster
Copy link
Contributor Author

I felt pretty good about the UI we iterated on for the abstreet lane editor, where you could drag-and-drop lanes to re-order them, but deleting was a click-button action.

Good feedback, thanks! I think the A/B Street behavior is what we want to build towards here. This JS editor died off for a few months, and I want to get the ball rolling again by attempting #240 (comment). Drag-and-drop will come back, but maybe not with sortable.js. And having a separate button for deletion (instead of dragging a lane <-> a trash can) sounds like simpler UX too.

Copy link
Collaborator

@BudgieInWA BudgieInWA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mobile phone review, so I'm yet to run or play with the app, but the videos look great and the code is easy to follow. I've just added a couple of low-level comments.

node.innerHTML += `<div align="center">` + directionIcon(lane) + `</div>`;
node.innerHTML += `<div align="center">` + width(lane) + `</div>`;
node.innerHTML = `<div align="center">${typeIcon(lane)}</div>`;
node.innerHTML += `<div align="center">${directionIcon(lane)}</div>`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Micro optimisation point: the rule of thumb is that hitting the DOM is an order of magnitude slower than anything pure JS (the reason virtual-dom libraries make sense).

So innerHTML += should be avoided as a matter of habit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know. Fixed. I still wish there was a cheap + idiomatic way to turn a quick snippet of HTML into an element. Building up a fragment with template literals is very nice.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assigning to innerHTML is fine, it's just the append that is problematic, as described in this answer: https://stackoverflow.com/a/23339072

I think the template literals approach is a good style, just commit it to the DOM in one go :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhhh thank you, I understand now. Serializing to HTML and then parsing everything out again sounds awful!

I'll keep things as all objects for now, because the next step will need to make the direction arrow clickable. AFAICT, there's not a nice way to mix template literals and attaching callbacks, without assigning an ID and then looking it up, or making one callback / listener at the parent level

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using listeners on some parent can work well, especially using data- attributes instead of ids to communicate data.

function iconObj(name) {
var obj = document.createElement("img");
obj.src = `assets/${name}.svg`;
obj.className = "clickable";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use <button> when the semantics fit. It comes with a whole host of behaviours (like keyboard focus and activation, hover/active state etc.) and accessibility stuff. Even before we are paying attention to keyboard support or accessibility, it is a better baseline, imo.

This should be a button with an img inside it, and we can use CSS to remove the border, fix padding/margin etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point! Fixed

app.render();
};
} else {
// TODO Show greyed out
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the "buttons" were <button>s, we could use the disabled attr, which comes with default styles and appropriate behaviours. E.g. onclick will never be triggered.

(lane) => lane.type != "separator"
);

// All of the state is immutable, except for road. The source of truth for
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplicity gained by this approach is a huge win in my experience.

@dabreegster
Copy link
Contributor Author

PTAL, I switched over to always building up DOM elements, and using buttons.

@github-actions
Copy link

github-actions bot commented Nov 4, 2022

Benchmark for a1f16c4

Click to view benchmark
Test Base PR %
tests/224637155 6.7±0.35µs 6.6±0.33µs -1.49%
tests/380103730 Japanese Expressway 8.6±0.50µs 8.9±0.44µs +3.49%
tests/389654080 11.1±0.39µs 10.8±0.62µs -2.70%
tests/49207928 cycleway:BACKWARD=lane 8.2±0.43µs 8.0±0.48µs -2.44%
tests/8591383 a bidirectional cycleway, oneway:bicycle 9.3±0.59µs 9.1±0.39µs -2.15%
tests/bus:lanes=designated| 8.6±0.62µs 8.4±0.43µs -2.33%
tests/busway=lane 7.6±0.34µs 7.6±0.37µs 0.00%
tests/cycleway=lane 7.8±0.37µs 7.7±0.40µs -1.28%
tests/cycleway=opposite oneway=yes oneway:bicycle=no 7.5±0.35µs 7.5±0.33µs 0.00%
tests/cycleway=opposite_track oneway=yes, deprecated 8.7±0.46µs 8.8±0.49µs +1.15%
tests/sidewalk:right=yes 6.9±0.38µs 7.0±0.41µs +1.45%
tests/sidewalk=both 7.0±0.32µs 7.2±0.30µs +2.86%

Copy link
Collaborator

@BudgieInWA BudgieInWA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got it running locally, and it's looking good!

Co-authored-by: Ben Ritter <[email protected]>
@dabreegster dabreegster merged commit 4f0466e into main Nov 5, 2022
@dabreegster dabreegster deleted the dragless_drop_editor branch November 5, 2022 09:57
@github-actions
Copy link

github-actions bot commented Nov 5, 2022

Benchmark for 36b719a

Click to view benchmark
Test Base PR %
tests/224637155 5.4±0.00µs 5.4±0.08µs 0.00%
tests/380103730 Japanese Expressway 7.3±0.07µs 7.3±0.06µs 0.00%
tests/389654080 8.8±0.01µs 8.8±0.02µs 0.00%
tests/49207928 cycleway:BACKWARD=lane 6.6±0.01µs 6.6±0.01µs 0.00%
tests/8591383 a bidirectional cycleway, oneway:bicycle 7.4±0.01µs 7.4±0.01µs 0.00%
tests/bus:lanes=designated| 6.7±0.00µs 6.8±0.01µs +1.49%
tests/busway=lane 6.1±0.06µs 6.1±0.02µs 0.00%
tests/cycleway=lane 6.3±0.02µs 6.3±0.00µs 0.00%
tests/cycleway=opposite oneway=yes oneway:bicycle=no 5.9±0.01µs 5.9±0.00µs 0.00%
tests/cycleway=opposite_track oneway=yes, deprecated 6.9±0.01µs 6.9±0.01µs 0.00%
tests/sidewalk:right=yes 5.5±0.00µs 5.5±0.01µs 0.00%
tests/sidewalk=both 5.7±0.02µs 5.8±0.02µs +1.75%

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants