Is it possible to get the current viewport Range (the visible part of the page inside the browser) using XUL functions from Javascript or plain Javascript?
Thank you!
For the viewport you need to use document.documentElement.scrollTop/scrollLeft/scrollHeight/scrollWidth. There is a slight complication: I think that in quirks mode (document.compatMode is "BackCompat") you need to check these properties on document.body instead of document.documentElement.
See https://developer.mozilla.org/en/DOM/element.scrollTop for documentation.
Edit: It seems that you aren't really interested in the viewport but rather its contents. AFAIK there is no generic way to get the contents of a particular area of the web page. It definitely cannot be described by a single Range object, rather a set of ranges. And even then: if the element has lots of text and all of it is a single TextNode, you won't know which parts of the text are visible and which are not.
However, in some special cases (particularly when the page structure is simple) you might be able to learn what text is being displayed by using range.getBoundingClientRect(). You start by selecting everything in your range and reducing that selection until the range size is within viewport boundaries.
Here is an example that does it for a vertically scrollable <div> containing lots of text: http://jsfiddle.net/5vEdP/ (tested in Firefox 6, Chrome 14 and IE 9). It first needs to make sure that each text character is placed into its own TextNode, otherwise you won't be able to select it separately in a Range object. It then selects the container of the text and moves the start of the range until the top boundary of the range is below the top boundary of the container. And then it does the same thing for the bottom boundary by moving the end of the range. In the end you get a range that selected only the text nodes that are fully visible.
width :document.body.offsetWidth;
height :document.body.offsetHeight;
HERE are better examples for various browsers
Related
Have a look at this video. In MS Word, one can drag any element anywhere. Based on that, the remaining content (only text, in this video example) reflows and wraps to fit. For example, when two images are side by side and one is dragged away or towards the other, the text in between shrinks or expands accordingly.
Is it anyhow possible to mimic such behavior in HTML, with Javascript? The biggest difficulty I find is the fact that elements own their content in HTML. So, a span owns its text, a div owns its text. But in the video, we can see that the text element in between the images hasn't exactly any content of its own, it gets whatever fits into it while transferring text from left to right. That is why, its content changes with change in orientation. Also, its text is not continuous. It contains bits and pieces of multiple sentences.
Are such manipulations possible with HTML and Javascript? If so, any heads-up will be nice...
Have a look at css exculsions:
http://adobe.github.com/web-platform/samples/css-exclusions/
it might help you acheive what you want. note that it is an experimental feature.
I'm writing some code that wraps various content into columns of text (and images, videos, etc). The code works fine, but due to the algorithm I'm using it's rather slow, specifically this general logic:
add something (text for this example) to a column
check to see if column.scrollHeight > column.offsetHeight (this requires a DOM reflow)
if yes, start to binary split the text until it's shorter
Basically my issue is that I'm adding an unknown amount of text to a column, so after each chunk of text I check the column's scroll height which requires the browser to actively reflow the DOM in order to give me the correct scrollHeight. So I have 50-100 or more reflows in order to properly lay everything out.
Any general ideas on how to avoid most of these?
You could render the content multiple times. Since the first time would cache it, this should be fairly fast. The reason for the multiple rendering would be as follows.
Render the original content in a hidden area
Check to see what the column width is compared to content
Overlay the content over the column, but beneath the page. This
will cut off part of the content that is overflowing. You can accomplish with
z-indexing or with overflow: hidden;
Based on what the check from step 2 was, overlay a copy of the content with
the calculated offset in the next column in the same fashion, hiding the
extra content.
Keep track of the rendered content versus total content so you can tell how many
columns you need to do this to if there are multiple columns.
Maybe this is the same thing Travis J is suggesting, but I'm not sure, I don't quite understand his solution.
You could render everything first, on a single column, then loop through the elements top-down to know when to split, based on your desired column height versus each element's offsetTop plus height. When you find an element to break at, cache its position and go on. At the end you should have an array with the list of elements to break at, so you can actually split the content in columns.
Does this make any sense to you?
Is there any JS/CSS/jQuery magic I can work to identify whether the last visible bit of content in a div is being cut off, and slightly increase/decrease the DIV's height to prevent the cut off text?
Our system allows the user to enter "elements" containing XHTML (using a Telerik Edit control). We have an ElementList page, where we show all the user-entered elements. However, since the user-entered XHTML can be very large, on the list page we only want to show the first 3 lines of each. So I set the DIV containing the XHTML to a specific height equal to 3 rows of text, and set overflow: hidden. So far, so good.
However, since the user can enter XHTML, they can create tables with padding (or otherwise diverge from standard text height). The text within those cells appears to be sliced off horizontally, due to the combination of height and overflow: hidden. Our requirements person doesn't like the look of this; but of course we cannot restrict the XHTML editable by the end user.
Here is a JSFiddle example of the issue.
This question is not a duplicate of:
"Stopping cut off text in variable height div..." as that question involves "webkit-line-clamp" which is irrelevant to my situation. (and in any case, that question was never answered)
"Cut text by height, no truncate" as that question is about a DIV containing pure text; my DIV contains XHTML. You'll note in the JSFiddle that I'm already sizing the DIV height using the em measurement.
This issue has me completely baffled - I'm hoping the SO community can come to my rescue!
UPDATE:
Ultimately, I suspect this cannot be resolved using HTML/JS/jQuery. In fact, you can craft a table (or series of DIVs) with gradually increasing top-margins, such that there's no way to avoid slicing at least one of them.
Thanks to all for their responses. I'm marking one as an answer, because in my opinion, it's a particularly simple/elegant workaround.
This is not the solution you were looking for, but it might be a good design workaround.
I put a white gradient in the bottom of the div, so that it creates sort of a "visual ellipsis"
Take a look: http://jsfiddle.net/robertofrega/LkYjs/3/
It is not as ugly as when the text is simply cut.
Your trouble is coming from overflow:hidden;. This line is doing exactly what you tell it to do, namely hiding the overflow. Can you use overflow-y: auto or something like that? That along with a grippy (like SO uses on its text areas), should help you out.
Instead of having overflow:hidden, you could set it to auto and then check for the presence of a scrollbar upon submission of the content. See this thread:
detect elements overflow using jquery
Try CSS3 property: text-overflow and set it to ellipsis, the default value is clip
Ok so the story is my users need a multi-select dropdownlist, which doesn't exist in ASP.NET, so the simple solution I'm going with is I'm using listboxes with multiselect on and I start them off at size 1, and onmouseover I change the size to say 10, onmouseout sets it back to one. Simple enough and the users don't know the difference.
Now, my issue comes from the fact that since I have any number of controls on my web app, I've set these listboxes to higher z-index numbers than the other controls, which creates a problem: on my listboxes closer to the bottom of the page the list expands below and not above, and part of the listbox goes under the bottom of the page but since onmouseout resets the size of the listbox I can't scroll the page down.
Does anybody know what I need to set to make it expand up instead of down?
edit Also, some may ask "why don't you just rearrange the listbox to a higher position in the page," the reason this isn't a viable option is I have well over 40 controls on the page and it they're grouped cohesively, I didn't just randomly place them where they are.(ie. investment info in one section, account in another, suitability in another)
EDIT: It's worth noting that the jQuery version of the below will be more compact and, in my opinion, more easily understood.
Glo, the code you have currently would be helpful here, especially since it seems you will have difficulty changing anything we give, or implementing what we might describe. Anyway, this works as intended in IE7, Firefox, and Opera; Safari and Chrome go quirky with it: http://jsfiddle.net/bUFzq/35/ (modified from http://www.plus2net.com/html_tutorial/html_frmddl.php).
The CSS just makes the select position-able relative to its default placement. Elements can only be positioned relative to other positioned elements. `position: relative;' leaves the element where it was until you move it, unlike absolute and fixed. It also positions relative to the edges of its nearest positioned ancestor. (The IT industry has the unfortunate convention of increasing Y downward rather than upward; just a heads up - or down.)
element.offsetHeight is the computed height of the element - how big it appears on the screen. element.style.bottom (like its cousins top, left, and right) sets the element's offset from the corresponding edge, in the direction of the element's center. setAttribute is fairly self-explanatory; it acts as if you were actually editing the HTML. Most properties of element.style (that aren't on all other objects) represent and modify similarly named CSS properties. For example, element.style.backgroundColor sets the background-color property.
addEvent is a function copied from Dustin Diaz's Rock Solid addEvent() because the browsers don't agree very well on how to do events. However, I would have put his script in a separate file and mine in yet another if I weren't working within a single script area. I did the `var addEvent = init();' thing just so you wouldn't have to scroll through his source, even though it is a good example of good code.
mouseover & mouseout are the actual listeners, explicitly called using apply 1) because I needed that height value for later and 2) because for some reason (at least within jsFiddle) it doesn't start out in the correct position, and only if the listeners are called in that order will it get there.
I have an HTML textarea as a basis for a small text editor running inside Chrome, which includes search functionality (as I need search features beyond what the browser offers). For longer texts, this means I need the JavaScript to scroll to the correct position after selecting the found text. This works fine by calculating the font's line height times the found text's row number (the latter I get by counting line breaks) and then setting textareaElement.scrollTop... but only when the textarea is set to wrap="off". When it wraps, as I sometimes need it, I cannot simply count the rows by counting line breaks, and my scroll position algo will be off by a bit.
What can I do to get the correct position of the found, selected text?
I've tackled this issue for the search feature of the logging console in log4javascript. My code surrounds search results in tags whose style properties are changed as you flick through search results. Initially I called scrollIntoView() on the current search result span but I think I had problems in certain browsers (log4javascript supports IE 5, for example) and ended up writing my own scrolling function based on the offsetLeft and offsetTop properties of the span and the scrollLeft and scrollTop properties of the container. I suspect scrollIntoView() will work fine in Chrome though so you should be OK just using that.