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)
Related
Some aspects of HTML5 and especially Canvas seem to have remain in the pre-word-processor software era, in the 60's when only typewriters existed.
(This issue) For one, you can't make a word or a sentence bold, or underline it inside a text on the same pass, simply and efficiently.
Filltext just fills canvas with a single piece of text and a single style and that's it.
(BTW, a second one is the lack of text-justifying function on both sides for canvas, so I had to made such a function myself using JavaScript.
A third, is a bug that prevents changing multiple custom fonts on subsequent canvas operations unless you have pre-use them(!) after initiation (I discovered that workaround after a lot of struggle).
So I'm thinking of two workarounds:
Locate the set of words you want to change the style, calculate the start x,y position and the total length using 'measureText', do the first pass replacing them with spaces, then do a second pass and only write those words with a different style inside the empty space.
Embed 2 or more styles on the same custom font and same language, like they were different languages in Unicode.
Is there another workaround?
I'm asking in case I'm missing something, or someone out there has a decent idea.
I need to determine the x/y screen coordinates of the last selected character on the HTML page within a given DIV element (not in a textarea) so that I can pop up a message next to it. If found something similar here on StackOverflow with a full example here.
Unfortunately that example places the text left-aligned to the last selected line and I need to put it at the end of the last selected line. Using getBoundingClientRect for the selected text doesn’t work when selecting multiple lines of text as when I try to right-align the popup it will always be at the very right of the screen.
sel.getRangeAt(0).getBoundingClientRect();
Is there a way using only JavaScript to find the x/y coordinates of the last selected character?
I expect the best way will be to insert the element into the DOM and let the browser worry about where on screen that is (at any particular moment). The accepted answer at javascript selection/range coordinates works something like that.
(If you only want to affect some part of the screen, you should be able to filter based on the selection range's node information.)
The other concern I would have is, depending on user agent (especially where accessibility adaptations might be in play) it could be faulty to assume a selection change would correspond to a given input event. You might want to look at the selection API and see if the events it defines are suitable to your purpose.
I'm trying to implement a utility to accurately clamp multi-line text to a given maximum number of lines. The approach I'm taking is to binary search the text of the element to find the maximum number of words where if the element contains only those words and an ellipsis, its height is not greater than what I determine is the height for N lines.
Since this is basically a trial-and-error method, I'll need to change an element that's actually rendered and check its size. I'd like it to be some other element than the actual one the user sees, because it'd be weird to have its contents blink around for a bit as the page loads. But since the clamp location will very much depend on the precise styling of the original element, I think what I'll need is to make an exact duplicate of it that's not visible to the user but still has the browser lay it out.
How do I accomplish this using JavaScript or jQuery?
I've considered creating an element at say x=-1000000, y=-1000000, and set its style properties to the uhh... computed style of the original element? I don't think that would actually work because the computed style already considers the current content of the element. What I need is some way to get all the style declarations that apply to the given element; or maybe make the new element an absolutely positioned sibling of the original, but since that's outside the regular block flow, I'm not sure its sizing would work the same.
Or is there some general way to make 'invisible' temporary changes to the style of an element that still let me access what the rendering engine makes of them?
I'm developing a web-based text editor without any contentEditable, textarea or input things. The biggest portion of my work is to measure widths of text on the left (right) side from the current caret position and moving the caret in the text.
For example when user presse the DOWN key a current left-offset of the caret must be computed and on the line below a character which's position is most similar must be found.
One very convenient way to do is to use one DOM element per character - I can just look at the offsetLeft property. Also, positioning the caret is much easier. Actually, everything is easier.
However I'm very unsure about the performance implications. I have seen this technique (or similar) used on some web-based JavaScript "IDE"s and it works just fine there.
Do you have any hints, tips?
Do you know some other fast way how to measure width of text. I want to avoid putting sections of a line to a DOM element and measuring its width each time as I think it will be much slower.
EDIT: I'm mostly asking about the main fact of EXISTENCE of many dom elements. How to do the measuring is a different thing.
I've seen this done (unfortunately can't find the link now) by using a canvas object and its measureText() method - basically you can ask a canvas "what size would this piece of text be if i rendered it in this style?" and use that to determine your caret position on the surrounding lines. This is performant, but of course it will only work in HTML5-capable browsers, and maybe not all of them.
But frankly this sounds like a big pain in the neck and probably more trouble than it's worth for an in-browser editor :)
You might be interested in this, which is a javascript implementation of the VI text editor. Unfortunately it does use a textarea, however not in the typical manner.
I have a small <p> about 140px wide aligned next to a picture. In total there is space for four lines of text. The first two lines are reserved for the title and there are two lines of other info.
I want the title to be cut if it spans more than two lines else it will push the other info out of line with the bottom of the image.
The only solution I could think of was to create a div the height of two lines with an overflow to hidden. However, if the title is only one line it leaves a big gap.
The solution can be Jquery, plain javascript, CSS or even PHP (if its possible).
TIA
Set the title to have a max-height of two lines
Keep in mind that the property max-height is not supported in IE6. In addition, limiting the size of text boxes can cause accessibility issues, and is generally not recommended.
As this is more of a content issue than a display issue, it's probably best to deal with it on the back end - if it's dynamic text, limit your database field to an appropriate character count, or chop it with some php (or whatever server side situation you're set up in). It's tough to establish a character count with a non-monospaced font, but if you don't limit it on the content side, you run the risk of upsetting your less visually-inclined users who may be using older browsers that don't zoom all fancy like the latest releases of safari and chrome.