Splitting HTML Text Content into Groups while Preserving HTML Layout - javascript

I'm currently wondering about the ability to apply dynamic formatting to content in an HTML page without changing the flow rules. At face value, this might seem simple, since you can select a subset of the DOM and mass-apply. However, this would not work if you wanted to apply that formatting to a only one part of the text for a particular object.
For example, formatting:
<div>Let's start my format here <span> and here </span> and <br> here too. <br> But not here.</div>
If you wanted to exclude <br> But not here. from your formatting there is no clear way to do it for the case of an arbitrary layout, even if you did so manually. One approach is to break the div into span sections, then format them differently. Unfortunately, wrapping arbitrary HTML in inline elements causes some unfortunate side-effects (e.g., any <br> tag in a span will be treated as if it doesn't exist). Using a block element wrapper, like introduces similar issues by adding breaks that didn't exist. I cannot seem to find a way to declare a DOM group that can just plain act as if it were plain text within the parent object.
So then, I'm trying to figure out a good general workaround to introduce display-level formatting while preserving any layout formatting. This kind of formatting could include text formatting (e.g., highlighting, emphasis) or dynamic effects (e.g., hide/reveal). I can think of a few hypothetical solutions, but I am not sure what (if any) actually are possible in practice:
An existing inline layout element like span that doesn't kill your line breaks and other formatting requests.
The ability to make a custom element such as #1 using CSS. Maybe the run-in or inherit display tags might be useful for this purpose? (https://developer.mozilla.org/en-US/docs/Web/CSS/display) Neither of them seem like they solve this issue, however.
A way to prevent a span from clobbering formatting markup inside of it.
A grouping element that acts as a pass-through for layout formatting (i.e., is treated like untagged text for layout purposes) but allows display formatting.
One would think this would be a straightforward thing to do. After all, it's not hard to imagine wanting to split a div into two different sections that are text-formatted slightly differently, while retaining their layout formatting. However, I can't seem to find the right tool for this job.

After looking at this quite a while, the best that I came up with was to use span wrappers for the text nodes only, accompanied by clobbering the default CSS formats for spans. This had its drawbacks, but thankfully people often leave the basic span class alone.
However, considering it further, I think the best solution is actually to make a new type of span using webcomponents.js and then to make that span type always inherit the parent formatting. Particularly if that span type has a very arbitrary name (e.g., <span-(some guid)/>), that should be sufficient to prevent any chance of accidental conflict. I have also found that by wrapping only the text nodes, there is no chance of losing line breaks or other formatting, since those elements can never exist in a text node.
I am not necessarily saying this is the best answer, but it is the best one I've seen so far.

Related

How to manually manage text wrapping in HTML

When working with designers, they often are very picky about word wrap in the completed HTML page. Assuming that I'm working on a fixed layout (not-responsive), and the designer does not like the way text is wrapping, I can:
Adjust padding-right
Add manual <br> to break a line
Add manual to avoid a break (typically for orphan control)
(In my case, I'm designing for a specific mobile device, so I know the screen size, and can control the fonts. Also, making the designers happy is non-negotiable.)
The issue that I keep running into is that the text or layout will be updated later, and relics of this specific word wrap concern, which no longer apply, introduce issues we then need to fix.
So I'm wondering if anyone can suggest a strategy that:
Allows completely arbitrary control of word wrap in individual
cases; but,
Doesn't make everything so hard to maintain going forward
I'm open to procedural, algorithmic (javascript), or CSS-oriented suggestions.
Here is the strategy I chose. Time will tell how maintainable it is.
Do not edit the text content
Fix wrapping by adding CSS classes that change the way the text flows, but do not use attributes like width or padding that are already being used to control layout
Specifically:
.tighten {
letter-spacing: -0.011em;
}
.loosen {
letter-spacing: 0.011em;
}
.hyphenate {
-webkit-hyphens: auto;
-webkit-hyphenate-limit-after: 4;
-webkit-hyphenate-limit-before: 4;
}
It turns out that these imperceptible changes in spacing can make a huge difference in wrap. I actually have several variations of these classes, so I can try progressively more or less space to fix wrapping.
In severe cases, I use the hyphenate class (I'm only targeting iOS in this case).
In a future revision, when we change the text in a div, we can just remove the tighten, loosen, or hyphenate class from that div, and see if there are any wrap issues we need to correct. If there are, we go through the original trial-and-error of seeing which class gives the best look.
Use <pre> tag so you can insert preformated text.

Placing text characters w/ javascript without using a div

I am going to be placing a lot of characters and words all over a web page using absolute positioning. I could put each character in it's own div, then set it's position. Is there any other way to place an individual word or character on a page without putting it in a div (to save memory). I figure not (which is fine), but if there is another way I'd like to explore it.
Try using html canvas. It will allow you to draw text to it at any position you want. https://developer.mozilla.org/en/Drawing_text_using_a_canvas
You can use tags like <b> and set their css to font-weight: normal;.
If you are going to be worry about the DOM tree size, you can go ahead with this way of implementation. But what is the use of implementing this? There are plenty of jQuery and JavaScript snippets available right?
You will need some type of html tag surrounding the text or else you will have no way to apply CSS.
This cannot be done in the manner you are imagining. Anonymous boxes cannot be manipulated and, generally speaking, do not carry traditional properties. You will have to use a wrapper tag.
you can read more here: http://www.w3.org/TR/CSS2/visuren.html#anonymous-block-level

Word Wrap in Raphael JS / SVG

How do you get words to wrap inside a box in RaphaelJS? Or in browser-based SVG in general?
I found this thread on it, but it doesn't make any sense. They say to use "widthToCharNum" but as far as I can tell, this thread is the only place those words have ever been used on the internet. They suggest using a "width" attribute, but this has no effect.
Text-wrapping is not built into Raphael or the SVG spec. Period. Coming from the HTML world, I found the absence of text wrapping pretty shocking.
However, you can do it yourself without too much difficulty. See this question for details and an example. Unfortunately, you have to burn some client-side cycles to make it work dynamically.
The svg.js library has a svg.textflow.js plugin. It's not ultra fast but it does the trick. It even stores overflowing text in a data attribute so you can use it to create continuously flowing columns. Here the text flow example page.
The tspan tag can give the illusion of word wrap, but there is no built in word wrap functionality.
The tspan tag is identical to the text tag but can be nested inside text tags and inside itself. Coupled with the 'dy' attribute this allows the illusion of word wrap in SVG 1.1. Note that 'dy' is relative to the last glyph (character) drawn. There is a tutorial on how to use tspan at http://tutorials.jenkov.com/svg/text-element.html.
The article at http://www.xml.com/pub/a/2002/09/11/quint.html might also be useful.
I know it's a little belated now, but you might be interested in my Raphael-paragraph project.
It's a small library that allows you to create auto-wrapped multiline text with maximum width and height constraints, line height and text style configuration. It's still quite beta-ish and requires a lot of optimization, but it should work for your purposes.
Usage examples and documentation are provided on the GitHub page.

How should I handle this CSS Inheritance conundrum?

I have a class of images called glyphs that appear through out my site. Once upon a time they were all called just called glyph. They used to only appear in one box. That box was a specific size and I used a javascript method to make sure the text always fit and the glyphs were always about the same height as the rest of the text. This was easy to do and the glyphs started off with a default due to my style sheet.
Now, I've decided to include multiple boxes per page with variable amounts of text. Each box gets sized independently. I've tried delaying the sizing routine, but this is highly reliant on a user's connection speed. If I don't run the sizing routine then things don't look right at all, so I'd at least like to pick a default starting size for everything. Of course, you can't size stuff with javascript until it has been loaded. Snake eats tail.
So basically, now that I have more than one box, each glyph gets a class glyph:1, glyph:2, etc. This number can go as large as the number of user submitted items on my site. How does CSS handle this? These items basically need two class names as far as I can see. But I'm pretty sure that's not allowed.
What I need: Set all images classes that begin with "glyph:" to 1em
This doesn't exist, right? glyph:*
Also, : is probably bad to use in a css class name, huh?
Don't use the : symbol. you can have more than one class for an element so do it like so
<div class="glyph glyph-1">Foo</div>
<div class="glyph glyph-2">Foo</div>
<div class="glyph glyph-3">Foo</div>
<div class="glyph glyph-4">Foo</div>
As others have said, you shouldn't use the colon symbol in class names. Hyphens and dashes are the only punctuation that is sensible to use.
It is possible to use colons in classes and escape them in your CSS code, but it gets really messy and is unnecessary.
Secondly (and this is where I'll go further than the other answers), if you're generating unique class names for your elements then you're probably doing something wrong.
The id attribute is there to give your elements a unique name; the class is intended to allow you to apply the same class (or classes) to multiple elements, thus allowing you to style all those elements the same. You probably know this already; I guess what I'm saying is that it sounds like you should be using id rather than class.
Next: You say you're pretty sure two class names is not allowed, but in fact it is allowed. It is perfectly permissible to have class="glyph bob" and your element will pick up styles from both class glyph and class bob. You can have as many classes as you like. I would still say, however, that if you want to give them unique names, it should be an ID.
You also ask for CSS syntax to set all the glyph* classes. Again, you're wrong: this syntax does exist, via the extended attr syntax:
[class^="glyph"] {
/*styles here for classes beginning with 'glyph'
}
You talk about delaying the sizing routine, and the problems that introduces. One solution to this could be to have the items hidden entirely until the browser has finished working out how they should look. You could even fade them into view or something to make it look like it was a deliberate effect.
But after all that, I'm left wondering why you're putting glyphs in images and sizing them independently? It all sounds a bit odd; your description in the question leaves me wondering what you're trying to achieve.
Have you considered using scalable graphics (SVG/VML) or a custom font for your glyphs, rather than images? If you used a custom font, you could simply specify the font size as normal, and let the browser work it all out.
Hope some of that was helpful.
CSS class names can't contain the : symbol. Everything after the : will be interpreted as a pseudo-class (like :hover) and will not be parsed properly.
As for your classes, why do they all have to be unique? Classes are made to select multiple elements at once, so you can just do this:
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
And select them all with one selector:
.glyph {
color: red;
}

Webkit columns find range of visible text

I have a piece of HTML which I am displaying inside a UIWebView using Webkit stylesheet attributes. I use Webkit to display the HTML in columns in order to simulate a book.
Only one column is visible at a time (one column represents one page). Now, I am trying to find the range of the visible HTML so that I can insert a span element right before the first visible word.
I managed to get the HTML element which contains the first visible word by using the JavaScript function, document.elementAtPoint(I might have the function name wrong), and changed its CSS class. but that just isn't accurate enough for me. I need it to be accurate up to the first visible word.
The idea is the create a column break at the first visible word when the fontsize is increased or decreased. I can using JavaScript to figure out in which column the element is, and programmatically scroll the user to that column, but first I need to get the element in there.
Can anyone help me?
The CSSOM View Module specification adds caretPositionFromPoint(x, y) to the Document interface, which returns a caret position for the specified x and y co-ordinates. WebKit supports caretRangeFromPoint, a close analogue from an earlier specification, which returns a Range.
It is possible that the word has been hyphenated and thus spans two columns, so rather than wrapping the first word in a span you may wish to consider the more naive approach of inserting the span directly at the cursor point. Here's an example:
var caretPos = document.caretRangeFromPoint(x, y);
if (caretPos)
caretPos.insertNode(document.createElement('span'));
Demo (WebKit only—click to insert spans): http://jsfiddle.net/Jordan/Aw9aV/
One final consideration: it is possible that WebKit will eventually stop supporting caretRangeFromPoint in lieu of caretPositionFromPoint; if so, you will need to adapt your code. Also note that the latter returns a CaretPosition which may not implement the insertNode method. The spec is still at WD, so be mindful that it is still in flux.
Ok, nog entirely sure what you are currently doing, but at the very least I should be able to give some useful tips, as I have some experience building page browsing systems in javascript.
First of all, in CSS3 you can define columns https://developer.mozilla.org/en/CSS3_Columns , which will automatically split up the content into different columns within a single element (where a single column has the full width of the uiwebview) and next add browsing controls which move the entire element containing the element (using css3 3d translations for smooth hardware accelerated motion and you know the width of the columns so you don't need to worry about what the first word on the page is). In which case you don't need to worry about splitting up the column breaks yourself. (Though, as I said, I am not sure to what extend you are already doing this).
Alternatively you may decide to wrap all your content in small inline-blocks (as older column implementations did) or even up to the point of single inline elements, each containing a single word. (Though this doesn't seem necessary anymore)
Lastly, work is being done on http://www.w3.org/TR/css3-regions/ which will make this even easier in the future, but for now it's only available in chrome and ie10
On the other hand, you might already be doing this or I might be missing the point, in which case I would need to see some code before I can give you a more specific answer. (I can think of various javascript tricks to work with letters within a text, but none seem necessary in your case)

Categories