dseif / slide-drive

Slideshow using audio/video to drive content
45 stars 9 forks source link

Selecting/Copying Text Should Work Properly #42

Open banksJeremy opened 12 years ago

banksJeremy commented 12 years ago

In Chrome you can select and copy text from the SVG, but the copied text has no whitespace is full of useless line breaks but doesn't incude any spaces.

In Firefox you can't even select text.

Being able to copy text is an important feature. It might require a slightly hacky solution, but this should be fixed.

banksJeremy commented 12 years ago

GitHub clobbered the contents of this comment when I submitted an edit to my most recent comment after pressing back to return to this page. Apparently it got confused about what comment I was editing.

I had suggested trying the space="preserve" attribute, using a different font because the empty glyph defined in the custom font may be causing errors, and replacing spaces with non-breaking spaces.

It's ironic that GitHub of all people have no record or indication of edited posts.

banksJeremy commented 12 years ago

Changing the space attribute and the font had no effect.

Replacing space characters with non-breaking spaces allows them to be copied, but removing whitespace from between nodes doesn't affect the line breaks. <text> elements seem to be treated like HTML block elements; they're split onto different lines even if there are no whitespace characters between them. I've posted a question on Stack Overflow asking about this.

banksJeremy commented 12 years ago

I was consulting the SVG spec to see if it described this behaviour. It turns out that you aren't even supposed to be able to select multiple <text> elements at once! (Opera obeys this.)

However, from the spec it looks like we could fix this by replacing each <g> element representing a block of text with a <text>, and replace the <text> elements it contains with <tspan>s. This would also solve our collapsing-spaces problem more elegantly than using non-breaking spaces.

In SVG Tiny, <tspan> doesn't support the required x and y attributes, but I think the browsers we're targeting should support full SVG. I'll give this a shot.

banksJeremy commented 12 years ago

Using <text> and <tspan> as described above worked properly in a test document.

I tried two different approaches to transforming the imported SVG, but both resulted in invisible text despite the DOM looking correct.

It finally occurred to me to try copying the HTML of the modified elements to an external document to see what happened. They showed up and could be copied correctly (in Chrome)!

I don't know what's causing this misbehaviour, but I have a (slightly crude) working solution: convert the SVG back to XML source, then re-parse it. It works (in Chrome)!

Software Carpentry in 90 Seconds Greg Wilson February 2012 Text in the star? Text on the star, really.

dseif commented 12 years ago

Looks good to me, is there a pull request for this?

banksJeremy commented 12 years ago

60

banksJeremy commented 12 years ago

I've been working on Firefox in my svg-container branch. It's working for every SVG I test it with, though it isn't yet working in Butter.

I've moved all of the little SVG utilities to their own class in a separate file, SVGContainer.

  var svgContainerEl = SVGContainer( svgSlide )
    .padTextViewports().fixXlinkAttrs().reparse().fixTextSelection() // fix text selection in Firefox
    .joinAdjacentTextEls().fixXlinkAttrs().reparse() // fix text selection in Chrome
    .fixXlinkAttrs() // prevent next reparsing from breaking in Chrome
    .scaleTo( "width" )
    .containerEl;

SVGContainer will wrap the SVG in a <div> responsible for scaling it appropriately, and fixTextSelection() will use this to position invisible <span>s on top of the SVG so that they can be selected.

For now, Firefox's text all ends up on a single line; fixTextSelection() is ignorant of text groupings. It also doesn't handle text that has been rotated... that might be easy enough to fix with CSS3 transformations once text groupings are considered.

banksJeremy commented 12 years ago

Dear GitHub,

Today I realized that the reason that things weren't working until I re-parsed was because I wasn't creating elements with the correct namespace. Even though HTML5 lets me just write <tspan> inside of an SVG, from JavaScript I still need to use createElementNS("http://www.w3.org/2000/svg", "tspan").

We would still encounter the issue with xlink: attributes when we're exporting, but nowhere else. This one case could have been handled in the getHTML event, rather than needing to re-parse right after the element is created.

Sincerely, Jeremy