Page MenuHomePhabricator

Should HTML formatting/DOM manip (presentation, responsiveness) be done in JS (frontend) or in PHP (backend)
Closed, ResolvedPublic

Description

As you know, Kartographer extension implements two tags: <mapframe> and <maplink>.

There are 2 possible scenarios, so far:

  • a map with absolute width: in pixels px.
  • a map with relative width: in percentage %.

Right now we only have a frameless presentation, but we want to support two presentations:

  • a frameless map.
  • a framed map, i.e. wrapped in a .thumb and .thumbinner container, offering the same look and feel as images.

We need to keep these 4 scenarios in mind when we implement responsiveness for both desktop and mobile:

  • a responsive frame and a map defined in pixels
  • a responsive frame and a map defined in percentage
  • a responsive frameless map defined in pixels
  • a responsive frameless map defined in percentages.

Goal of this task below

This is all doable with a bit of CSS and a few more dom containers, however there has been some discussions wether this work is better handled in the backend or in the frontend:

  • keeping the HTML in the PHP output as simple as possible (for caching and backward compatibility reasons), and handle the presentation/DOM manip in JavaScript (performance implication and maybe flash of unstyled content).
  • doing all the presentation work on the server in PHP, so map containers display correctly on page load and avoid redundant JS execution for each map on the page.

Please compare the current PHP output with the proposed output (4 possible scenarios), and advise whether the HTML formatting/DOM manip should be handled by the client or the server.

Current output below

For the comparison, this has been the PHP output so far:

<div class="mw-kartographer mw-kartographer-interactive floatright"
     mw-data="interface"
     style="width:200px; height:300px;"
     data-style="osm-intl"
     data-zoom="15"
     data-lat="37.8013"
     data-lon="-122.3988"
     data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]">
</div>

There is no distinction between absolute width and relative width, as shown below. But there is also no responsiveness, no frame/frameless option, and no caption text.

<div class="mw-kartographer mw-kartographer-interactive floatright"
     mw-data="interface"
     style="width:25%; height:300px;"
     data-style="osm-intl"
     data-zoom="15"
     data-lat="37.8013"
     data-lon="-122.3988"
     data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]">
</div>

Proposed output(s) below

I submitted this patch: https://gerrit.wikimedia.org/r/#/c/289978 that implements these 4 scenarios, and the entire work is done in PHP by the backend, so MapFrame can now have 4 different HTML outputs:

EDIT: It is important to note that these 4 outputs actually come from 4 different wikitext (pay attention to format and width attributes). In other words, 1 wikitext will always generate only 1 type of output, regardless of the platform/device.

  • a responsive frame and a map defined in pixels
<mapframe format="frame" width="200" height="300" zoom="15" longitude="-122.3988" latitude="37.8013" text="Map caption">
<div class="mw-kartographer-thumb thumb mw-kartographer-container floatright"
     style="max-width: 200px;">
    <div class="thumbinner">
        <div class="mw-kartographer-placeholder" style="padding-bottom: 150%;">
            <div class="mw-kartographer mw-kartographer-interactive"
                 mw-data="interface"
                 data-zoom="15"
                 data-lat="37.8013"
                 data-lon="-122.3988"
                 data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]"></div>
        </div>
        <div class="thumbcaption">Map caption</div>
    </div>
</div>
  • a responsive frame and a map defined in percentage
<mapframe format="frame" width="25%" height="300" zoom="15" longitude="-122.3988" latitude="37.8013" text="Map caption">
<div class="mw-kartographer-thumb thumb mw-kartographer-container floatright" style="width: 25%;">
    <div class="thumbinner">
        <div class="mw-kartographer-placeholder" style="height: 300px;">
            <div class="mw-kartographer mw-kartographer-interactive"
                 mw-data="interface"
                 data-zoom="15"
                 data-lat="37.8013"
                 data-lon="-122.3988"
                 data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]"></div>
        </div>
        <div class="thumbcaption">Map caption</div>
    </div>
</div>
  • a responsive frameless map defined in pixels
<mapframe format="frameless" width="200" height="300" zoom="15" longitude="-122.3988" latitude="37.8013">
<div class="mw-kartographer-container floatright" style="max-width: 200px;">
    <div class="mw-kartographer-placeholder" style="padding-bottom: 150%;">
        <div class="mw-kartographer mw-kartographer-interactive"
             mw-data="interface"
             data-zoom="15"
             data-lat="37.8013"
             data-lon="-122.3988"
             data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]"></div>
    </div>
</div>
  • a responsive frameless map defined in percentages.
<mapframe format="frameless" width="25%" height="300" zoom="15" longitude="-122.3988" latitude="37.8013" text="Map caption">
<div class="mw-kartographer-container floatright" style="width: 25%;">
    <div class="mw-kartographer-placeholder" style="height: 300px;">
        <div class="mw-kartographer mw-kartographer-interactive" 
             mw-data="interface" 
             data-zoom="15"
             data-lat="37.8013"
             data-lon="-122.3988"
             data-overlays="[&quot;_bc9920c5250401bb5f3f0c3b3785f57a7cb0b551&quot;]"></div>
    </div>
</div>

Event Timeline

Related patches:
https://gerrit.wikimedia.org/r/#/c/285648/ Responsiveness in JS - Merged
https://gerrit.wikimedia.org/r/#/c/290254/ Responsiveness in JS - In discussion
https://gerrit.wikimedia.org/r/#/c/289978/ Responsiveness + Frame/Frameless in PHP - In discussion

I've CC'd some Parsoid people but my instinct is to have fewer versions of HTML.

Responsiveness is decided by the skin and/or client, so shouldn't be part of the content HTML.

I would like anyone who has a concern with the PHP implementation to chime in.
If this ticket remains with no comments, I will decide to go with the PHP implementation.

Since different wikitext emits different HTML but the output doesn't change according to device, it seems like caching isn't affected.

Parsoid's output for media and images is determined by wikitext and parameters but HTML structural change is only for whether the image is meant to be rendered inline or as a block. The HTML structure is identical for frame/frameless/border/left/right as long as it is a block image. The alignment, border, frame or frameless parts are entirely controlled by CSS.

The approach taken by Parsoid seems a sensible route since it keeps the output uniform, consistent, and "semantic" -- presentational changes doesn't change HTML structure. This also enables applications that examine / consume output to be simple. They can identify semantic structure without having to worry about changes that are purely presentational.

I think that is what @Esanders is also recommending -- his instinct seems right and matches mine as well.

+1 to @ssastry. the consumers of the raw HTML DOM are gadgets and tools primarily -- for these folks it is important to have semantic markup. ideally all the information from the wikitext (especially caption) should be present in the DOM in stable locations, so that it is as easy as possible for consumers (search engines, gadgets, machine translation, machine learning) to parse the DOM and extract the relevant information.

It seems to me that the proposed PHP *almost* fulfils these goals, except that there's an extra <div class="thumbinner"> inserted sometimes. I'd suggest using a plain <div> in that location in the other cases as well to keep the structure always fixed. (It might also be preferable to put the data- attributes on the outermost element, all else being equal.)

Consider writing a CSS selector to extract captions. It looks like the following would be required:

.mw-kartographer-container > * > * + .thumbcaption

And to extract lat/long, something like:

.mw-kartographer-container > * > *[data-lat], .mw-kartographer-container > * > * > *[data-lat]

(due to the presence of the 'extra' <div> in the framed output -- and note that using strict child selectors is necessary because (in theory) the caption can itself contain another map).

Designing good semantic output is roughly equivalent to thinking about queries like these and seeing whether they could be made simpler.

See also T112991: Semantic image styles / beautiful layout where we are starting to get past the simplistic "framed versus frameless" layout model for figures, which doesn't really yield beautiful results on any platform.

Might be related: T137148 - Provide a way for interactive maps to be embedded externally (similar to how youtube videos can be embedded as an iframe with a link back to the source)

The final solution was:

    • Do not support relative widths. Only width="full", formerly width="100%" is supported.
    • The PHP output was kept as simple as possible. No extra JS manipulation needs to be done on the client side. It works cross-platform and is also responsive, meaning it will fit to the available width if too large.
  • The frame output is:
<mapframe text="caption text" latitude=10 longitude=20 zoom=13 width=640 height=480/>

gives:

<div class="mw-kartographer-container thumb tright">
  <div class="thumbinner" style="width: 640px;">
    <div class="mw-kartographer-map" mw-data="interface" data-style="osm-intl" data-width="640" data-height="480" data-zoom="13" data-lat="10" data-lon="20" style="height: 480px;"></div>
    <div class="thumbcaption">caption text</div>
  </div>
</div>
  • The frameless output is:
<mapframe latitude=10 longitude=20 zoom=13 width=50% height=480 frameless />

gives:

<div class="mw-kartographer-map mw-kartographer-container floatleft" mw-data="interface" data-style="osm-intl" data-width="640" data-height="480" data-zoom="13" data-lat="10" data-lon="20" style="width: 640px; height: 480px;">
</div>
  • One can select a map using .mw-kartographer-map.
  • One can select an interactive map using .mw-kartographer-interactive. Note: this class is added once the map becomes interactive.
  • One can select a caption using .mw-kartographer-map + .thumbcaption.
  • One can extract lat/lon using .mw-kartographer-map[data-lat][data-lon].

The parsoid approach was considered, but the current state is too premature and this feature would be hard to implement in practice. Frames have been requested by the community for a long time, so we preferred the option of using existing .thumb/.thumbinner. This was discussed during last FrontEndStandards group and was approved, though the better Parsoid approach is preferred. We should revisit it once all images are using Parsoid markup and the CSS for the thumbnails is available on every page.

Thanks for every one involved in this discussion.