JavaScript: Find vertical pixel position of particular string in textarea - javascript

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.

Related

Need to get HTML Element's Layout information just like Firefox's debugger

I have a aspx.net grid control and i'm trying to copy the grid control's first row information into another table java script.
I'm getting width of each cell by parsing through the grid control's first row using the following code:
gridCtrl.rows[0].cells[x].clientWidth
where x is 1 to last cell
But some how the width doesn't match the width display by Firefox's layout width.
I tried debugging Firefox debugger and explored all the attributes to see if i mix match margin, padding, width etc to get the width displayed by the Firefox's Layout width.
But so far no luck.
I'm wonder any of the experts in the field could provide some help.
I'm looking for Something similar to the layout information provided by the Firefox debugger.
I want to get individual elements like
elements margin, border, padding and the actual width of element.
[Sorry since this is my first post i'm not allowed to post a pic, But if you open fire fox browser and hit F12 and select HTML/Layout. you will see the layout information i'm talking about]
Any help is appreciated.
Thanks,
I can't comment so I must post as a reply :(.
I think that the problem is that the element might have a width set initially, let's say 50px, but it can also adjust based on the amount of text in it. In this case, you should not get the rendered dimension because that one differs from browser to browser.
Also another problem that is see is if the element has a min-width and dynamic width based on the viewport's size. In this case it would not work either.
If I am correct your solution would be to write a JavaScript code that sends you the information.

Looking for ideas to quickly flow content

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?

Get the visible range in Firefox

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

expanding drop down area above instead of below with javascript

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.

Forcing scroll positioning with Javascript scrollLeft

I have a set of Javascript functions I use with a table of input elements to enable navigation. Things like keeping track of the currently focused element, and overflowing from the end of one row to the start of the next. I have scrollbar support with a fixed first column by creating one table that is only one column wide as my fixed column and having a scrollbar for the other table.
However, I have been noticing recently, that the default behavior of the scrollbar is a bit deficient. When I navigate to the last column, Firefox leaves that column partially obscured by the scrollbar instead of scrolling far enough to see it. Likewise, once I scroll over so I can see the other part of the last column, when I move on to the next row and the nav code sets focus to a cell in the first column (the frozen table), Firefox doesn't change the scrollbar so I can see all of the first column.
Because of this, I've been looking into how to modify scrollbar positioning using javascript. My table doesn't use a vertical scrollbar, only a horizontal one. So I stumbled upon scrollLeft.
document.getElementById("meastable").scrollLeft = 1; // reset scroll to leftmost
Unfortunately this seems to only work once in a while. When I enabled Firebug and traced through my navigation code where this line is, it seems to work once in a while, but most of the time, this line will run but the tables scroll left property is unchanged and I can't see a change visually either.
I also set scrollLeft to a high number so it will be set to the maximum as is described in the documentation, and that also does not work (except once in a while).
I use the following code to set up the scrollbar with my table.
<div style="overflow:auto">
<table id="meastable" border="1">
According to Mozilla's documentation, this seems to be something that originated in IE but now works in Firefox. Does this actually not work in Firefox as the inhouse project this is for will be Firefox only.
So I'm trying to figure out what's wrong. Is scrollLeft known to not work right, or should I go back and see if I've screwed something up in my definition of the scrollbar or something along those lines?
The containing div is the element with overflow. You need to set the scrollLeft of the div, not the table.

Categories