Use case
I want to detect if html tables get too wide, and if so, I want to flip the table header cells to become vertical (e.g. with writing-mode: vertical-lr;).
I want to update this on resize: If the viewport gets bigger, the text in the cells might become horizontal again.
The flip condition is whether the original table with horizontal labels would be wider than its container.
Question
How do I determine the width a table would have with horizontal labels, without changing the table itself?
Thoughts
My current idea would be to make an invisible copy of the table with horizontal labels, and use it as a "sensor". But I am afraid this will pollute the DOM and cause side effects somewhere. Also I would need to keep this copy updated all the time.
Is there a "best practice" or a known pattern to solve this problem?
It is actually quite simple:
We can change the css on the table during the script run. Once we query a property like element.width, this will cause a reflow during the script execution, but it won't cause a repaint. So this means we can do the test without the need for a cloned DOM element, and without visible changes.
See https://developers.google.com/speed/docs/insights/browser-reflow
Related
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
I'm creating a custom select plugin. Everything is going great, but the dropdowns (<ul>-objects) are overlapping on each other :(
I understand, that the overlapping order is set after the elements order on page or when they are created. So my question is: What is the method to make the latest opened/shown object (<ul>) on top of the hierarchy?
I just need the correct method. I'm not going to copy the full code, but a little example:
$('#trigger').click(function () {
new_dropdown.slideDown();
});
(A picture is worth of 1000 words)
So lets say, that I open the green select the last.. How can I make it on top of the yellow one?
EDIT
For easier testing I created jsfiddle. For future references I'll post the link: http://jsfiddle.net/hobobne/uZV5p/1/ This is the live demo of the problem at hand.
What you're looking for is the CSS z-index property (higher values put elements at the front).
You could probably just set them in ascending order (e.g. set green one to 1000, yellow to 1001), but if you really need to bring it to the front when clicked, you can change the z-index with javascript
var zindex=100;
$("#trigger").click( function() {
newdropdown.css('z-index', ++zindex);
});
Here's a demo: http://jsfiddle.net/waitinforatrain/Vf7Hu/ (click the red and blue divs to bring to front).
Edit: gilly3's approach is better, and as was mentioned there may be some issues with older versions of IE.
Two ways:
Set a z-index
Setting a z-index will change the default stacking order. You can have a counter that increments and use that to set the z-index of newly stacked items. You may have issues with IE 7 or earlier, though, and those can be fixed by setting the z-index of other items. https://developer.mozilla.org/en/Understanding_CSS_z-index/Adding_z-index
Use absolute positioning, and append the div to the body
If you use absolute positioning, you can append the div to the body and still have it appear below the element. If you append the div to the body, the one last added should be on top, because of the default stacking order.
Give it a class when it is opened, and remove that class from the previously opened ones:
$(".slidedown_active").removeClass("slidedown_active");
$(this).addClass(".slidedown_active");
Then your users can use z-index in their style definition for that class to ensure the active list is always visible.
The reason I don't recommend setting the z-index directly is because you can mess up your users' layout unnecessarily. These kind of overlap issues can be a real headache for a web developer. For a plugin to try to guess at how to resolve overlap issues, without any knowledge of the code or design, would be virtually impossible. Instead, give your users the tools they need to fix the overlap issues themselves. It may be that your users would never encounter overlap issues, so setting the z-index for them would be pointless at best, and potentially harmful.
Hey, Ive got an php script dragging some images from a database and displaying them using float:left; so they go left to right.
However unless in the css i define i width for the container they jump down onto a 2nd line.
So the question IS!
How for the life of me could I get it to figure out the width of the content and then set the width attribute via javascript all on the one load.
I did have a slight worry that this wouldnt be easily possible as it wud have had to render the images/layout first to get a width before then adjusting it.
Ideas please people!! x
Your question has to do with how the flows of floats work...
If two images are floated and the sum of their widths is wider than the containing element, they will wrap (similar to the way words in a paragraph wrap).
Visual references describing the flow of "float"ed elements (way too difficult to describe in a few words):
http://css.maxdesign.com.au/floatutorial/introduction.htm
The Flex tile containers will create and remove tiles as the data changes and seems good to use in areas where the content is dynamic. How to implement this functionality in HTML? I guess that we need to use some JS and/or CSS. Any inputs?
You can ignore CSS altogether (for layout) and do this the same way that flex implements it. Without providing code itself, here's the basic idea (assuming horizontal layout):
When you add a child, add it to the right of the previous sibling. (c.y = s.y+s.width).
Check if current child exceeds the width of the parent. (c.y + c.width > p.width). If so, drop it to the next "row".
Of course, things get more complicated depending on whether you want to do a TileContainer or a FlowContainer. Should the layout look like a grid, or should it be more organic like paragraph wrapping? (if all you want it paragraph wrapping, I think making everything "float:left" will do that for you, but correct me if I'm wrong.). Assuming the TileContainer idea, you just need to iterate over all the children and make sure they have the same height/width (== max child height, max child width), and then do the layout steps mentioned above. You may want to place each child in a container div for easier control of elements that don't resize nicely.
And lastly, just make sure you listen for any window resize events so you can run your layout algorithm.
Check out the algorithms in "TileBase.as" in Flex if you want tips, but it might be easier just to roll your own.