Breakable table row in HTML - css

Is there a way to make a table row breakable at a certain cell?
<table>
<tr>
<td>Some title descriptive text</td>
<td>nnumbers</td><td>Short text</td><td>datetime</td>
<tr>
... more rows
</table>
Now I would like this row to break after the first cell if the width of the viewport is too small (typically when used on mobile phones).
Is that achievable anyhow using html5 css3 and eventually some Javascript?

As of CSS2.1, it is possible by using appropriate display CSS attribute values. See this demo page:
http://dabblet.com/result/gist/1576044
...and the source:
http://dabblet.com/gist/1576044
Tested on a Galaxy Nexus phone, works, and should work for most Webkit-based mobile browsers. Also, it should work on Firefox Mobile and Opera, though I didn't test.
Long story short, use a media query to detect page width and set a max-width breakpoint and apply:
css
table, tbody, thead, tr, td, th { display: block }

No. Table rows cannot be broken onto multiple lines. That'd imply you want TWO rows of cells instead of a single.

I needed something just like this for a project of mine; i needed to support old browsers so it doesn't use HTML5, just javascript to check the overall width/amount of rows able to handle:
http://pastebin.com/raw.php?i=umFWx3mK (Just copy it inside an HTML file and open it with a browser)
$(window).resize(distribute)
$(document).ready(function(){
allboxes = $(".box");
$('#container').delegate(".box","mouseenter",function(){
$(this).addClass('current')
}).delegate(".box","mouseleave",function(){
$(this).removeClass('current')
});
table = $("#table");
distribute();
})
var lastfit, allboxes, table
function distribute(){
var fitAmount = Math.floor($("#container").width()/180);
if(lastfit!=fitAmount){
if(fitAmount<1){fitAmount=1}
lastfit = fitAmount;
var clones = allboxes.clone(),
emptycells = "", emptyrows = "",
trs = table.find("tr");
for(var i=0;i<fitAmount;i++){
emptycells += "<td> </td>";
}
trs.html(emptycells)
var count = trs.length*fitAmount
if(count < allboxes.length){
var newRows = Math.ceil((allboxes.length - count)/fitAmount);
for(var j=0;j<newRows;j++){
emptyrows += "<tr>"+emptycells+"</tr>";
}
}
table.append(emptyrows)
var tds = table.find("td"), trs = table.find("tr");
clones.each(function(index){
tds.eq(index).html("").append($(this))
})
allboxes = $(".box");
trs.filter(function(){ return !/box/gi.test(this.innerHTML) }).remove()
}
}
function boxmouseover(box){
$(box).css("background","red")
}
function boxmouseout(box){
$(box).css("background","#CCC")
}

Related

Adjusting custom view in Fullcalendar by Adam Shaw

I've followed the outlines in FullCalendar Change Week View to Vertical List instead of Horizontal Table Columns to create a custom vertical week view in fullcalendar.
The implementation is taken from the original post shown in this fiddle: http://jsfiddle.net/nomatteus/dVGN2/3/
This lays out the view like this:
<table>
<thead>
.tr.td.headercontent....
</thead>
<tbody>
.tr.td.eventcontent....
</tbody>
</table>
However the vertWeek view is used on small screens (smartphones etc), so I would like to have the day header and content to be layed out horizontal to take up less space in height like in this screenshot:
http://i.imgur.com/F4AkoSw.png
The MAN 8. is styled manually as I like it, but TIR 9 is how it is rendered by the view.
I would like to achieve this:
<table>
<thead>
</thead>
<tbody>
<tr>
<td> headercontent
<td> eventcontent
</tr>
</tbody>
</table>
I have tried to understand the fullcalendar code to move the header into the same as the eventcontent - but it seems like the view is rendered in different places for thead and tbody for that container.
Could anyone point me in the right direction on how to modify the code to achieve this?
Post of implemented answer for sharing:
Seems like my understandig was a litte bit inaccurate. The header was placed in an overlapping table above the table containing the events. Tried to traverse the DOM and place the header during the dayRender function, but the corresponding tbody for the event was not yet created.
Simplified illustration:
table
thead
**header**
tbody
table
thead
tbody (not created at dayRender, but available at eventRender)
**event*
The solution was quite simple - hide the .fc-day-number:
dayRender: function( date, cell ) {
// Get the current view
var view = $('#meal_calendar').fullCalendar('getView');
// Check if the view is the new vertWeek -
// in case you want to use different views you don't want to mess with all of them
if (view.name == 'vertWeek') {
// Hide the widget header - looks wierd otherwise
$('.fc-widget-header').hide();
// Remove the default day number with an empty space. Keeps the right height according to your font.
//$('.fc-day-number').html('<div class="fc-vertweek-day"> </div>');
$('.fc-day-number').hide();
// Create a new date string to put in place
var this_date = date.format('ddd, MMM Do');
// Place the new date into the cell header.
cell.append('<div class="fc-vertweek-header"><div class="fc-vertweek-day">'+this_date+'</div></div>');
}
},
In addition I styled the td.fc-event-container in my CSS like this:
td.fc-event-container {
padding-left: 68px;
}
Quite possibly a hack - hours to research, two lines to correct. But works for me......

Resize font depending on string length

I have a vertical menu and i want to make it localizable, but localized strings in menu elements often goes out off the edge.
So the question is how to make font resizable depending on the string length in CSS. And if possible, without JavaScript.
Thanks!
UPD: JQuery isn't acceptable. Any way in Pure JS?
You should make familiar with using plugins, they save you much time and of course they're very reliable (they are written by experienced scripters/programmers and have been tested by community). However looks like you want some pure JS solution. I've just made this code for you. It works fairly OK (although I'm not sure if it's as good as some plugins). The only requirement is the element (which you want to adjust the font-size accordingly to the text length) should contain plain text, not some HTML code.
The idea to implement it using pure JS is simple, you need some dummy element created using script, this dummy element is used to measure the size of the text. We need to adjust the font-size of the dummy element until the size of the text (as well as of the dummy element) should be confined to the size of the element (whose font-size you want to adjust). I made the code very clearly, hope you understand it better after reading the code:
//we just need 1 dummy element for the whole page.
var dummy = document.createElement('div');
dummy.className = 'dummy';
var inSingleLineMode, inMultilineMode;
//function used to adjust the font-size of the element
//so that the width is fixed (single-line mode) or both the width and height are
//fixed (multi-line mode), of course the text should be contained within
//the fixed width and height.
function adjustFontSize(element, singleLine){
if(!element.innerHTML) return;
var elementStyle = getComputedStyle(element);
dummy.style.font = elementStyle.font;
initMode(singleLine, function(){ dummy.style.width = elementStyle.width });
dummy.style.padding = elementStyle.padding;
dummy.style.boxSizing = elementStyle.boxSizing;
dummy.innerHTML = element.innerHTML;
document.body.appendChild(dummy);
var dummyStyle = getComputedStyle(dummy);
while(singleLine ? parseInt(dummyStyle.width) < parseInt(elementStyle.width) :
parseInt(dummyStyle.height) < parseInt(elementStyle.height)){
dummy.style.fontSize = parseFloat(dummyStyle.fontSize) + 1 + 'px';
dummyStyle = getComputedStyle(dummy);
}
while(singleLine ? parseInt(dummyStyle.width) > parseInt(elementStyle.width) :
parseInt(dummyStyle.height) > parseInt(elementStyle.height)){
dummy.style.fontSize = parseFloat(dummyStyle.fontSize) - 1 + 'px';
dummyStyle = getComputedStyle(dummy);
}
element.style.fontSize = dummyStyle.fontSize;
document.body.removeChild(dummy);
}
function initMode(singleLine, callback){
if(!dummy) return;
if(singleLine&&!inSingleLineMode) {
dummy.style.whiteSpace = 'nowrap';
dummy.style.width = 'auto';
dummy.style.display = "inline-block";
inSingleLineMode = true;
inMultiLineMode = false;
} else if(!singleLine&&!inMultilineMode) {
if(callback) callback();
dummy.style.whiteSpace = 'initial';
dummy.style.display = "block";
dummy.style.wordWrap = 'break-word';
inMultilineMode = true;
inSingleLineMode = false;
}
}
Demo.
In the demo, you can see that the first menu #menu1 is the Vietnamese word meaning Chrysanthemum while the second menu #menu2 is of course the English word Chrysanthemum. They have much different length, however both are supposed to have fixed width of 100px, hence the second menu #menu2 should have smaller font-size to fit the space.
You can use jQuery Text Fill like this.
Load up the plugin: <script src="jquery.textfill.js" ></script>
Put an id <input type="text" id="dyntext" value="e=mc²"></input>
Use the code to do magic. Preferably put this in <script> tags:
The end result will look something like this:
function update() {
var size = parseInt($('#maxsize').val(), 10);
if (!isNaN(size)) {
$('.dyntextval').html($('#dyntext').val());
$('.jtextfill').textfill({debug: true, maxFontPixels: size});
}
}
$(function () {
$('#maxsize').keyup(update);
$('#dyntext').keyup(update);
update()
});
This is not possible without Javascript. Using Javascript, you can use one of the many libraries, like FitText.
So you could use a Javascript library for this, but that would also mean that various labels have different font sizes.
I think the best approach would be to style the menu in such a way that it gracefully handles multi-line captions. That way, the length doesn't really matter much.
Because some language are 'longer' than others (for instance French labels are on avarage 1.5 to 2 times as long as English, it's a good idea to test your interface with one of those languages.
And for the font size, you could add a modifier on server side, for instace if you know the current language is French, you can add a class 'gui-captions-very-long' to the html tag and apply your CSS based on that class. That way, you can have a generic modifier which you can configure per language. I think that's a better solution than making all labels fit on a single line.
Keep in mind though, that smaller sizes are harder to read. You cannot just make the fonts half the size if the text is twice as long. You'll have to tune your design (or its implementation) to make longer texts possible.
I did look for that in the past then found an answer that really did the trick for me, but cannot remember were exactly... :(
But since it does answer the question using pure javascript and no plugins/libraries (did some optimisations since though), here it is! (with a working example):
// First we add a new function to the String prototype,
// this will be used to get the length of current string according
// to its font-family and font-size
String.prototype.textWidth = function(fontFamily, fontSize) {
var container = document.createElement('div');
container.style.visibility = 'hidden';
container.style.fontFamily = fontFamily;
container.style.fontSize = fontSize + 'px';
container.style.display = 'inline';
document.body.appendChild(container);
container.innerHTML = this;
var pxLength = container.offsetWidth;
container.parentNode.removeChild(container);
return pxLength;
};
// this is the function that will resize our text if it's too long
// classNameTarget (String) = the className of the element we need to resize e a
// tag or an id but you'll need to make modification to this function!
// maxWidth (int) = the max width (in px) of your final string
// fontFamily (String) = the family currently used by your string(wrong one might lead
// to wrong result!)
// fontSize (int) = the initial font-size of your string
var testWidth = function(classNameTarget, maxWidth, fontFamily, fontSize) {
maxWidth = maxWidth || 100;
// first we get all targets
var containers = document.getElementsByClassName(classNameTarget);
for (var i = 0; i < containers.length; i++) {
// for each of them we fetch their current length
var length = containers[i].innerHTML.textWidth(fontFamily, fontSize);
if (length > maxWidth){
// if the current length is bigger then we resize it by using a span styling with
// the new font-size
containers[i].innerHTML = "<span style=\"font-size:" + Math.floor(parseInt(fontSize) / (length / maxWidth)) + "px;\">" + containers[i].innerHTML + "</span>";
}
}
};
// we want our cell to have text no longer than 75px while having them starting at 50px
// font-size in arial
testWidth("firstname", 75, "arial", 50);
testWidth("lastname", 75, "arial", 50);
<table>
<thead>
<tr>
<th>firstname</th>
<th>lastname</th>
</tr>
</thead>
<tbody style="font-size: 50px; font-family: arial;">
<tr>
<td class="firstname">Bob</td>
<td class="lastname">Tomysonorubia</td>
</tr>
<tr>
<td class="firstname">John</td>
<td class="lastname">Doe</td>
</tr>
<tr>
<td class="firstname">François-Xavier</td>
<td class="lastname">De la nouvelle Orléan</td>
</tr>
</tbody>
</table>
the testWidth method might need some adjustements regarding your currents needs, perhaps you'ld like to look into querySelector or querySelectorAll to make it quite generic
I suggest an tiny example. On a pure JavaScript.
https://gist.github.com/dejurin/9bef02be6876e068ee276bee31cb3bcb
"use strict";
(function(w, d) {
var fit = d.getElementById("fit");
var wrap = d.getElementById("wrap");
fontFitResize(fit, wrap);
function fontFitResize(fit, wrap, step = 0.5) {
var currentSize;
while(fit.offsetWidth < wrap.offsetWidth) {
currentSize = parseFloat(w.getComputedStyle(wrap, null).getPropertyValue('font-size'));
wrap.style.fontSize = (currentSize - step) + 'px';
console.log(wrap.style.fontSize);
}
}
})(window, document);
.fit {
border: 1px solid #ff0000;
white-space:nowrap;
font-size:24px;
width:200px;
}
<div id="fit" class="fit">
<span id="wrap">Resize font depending on string length</span>
</div>

Hiding grid columns change height of rows

I have quite annoying problem with hiding grid columns dynamically. After I hide columns (with long text in cells), the height of grid rows dramatically increases.
Before hide
and after hide operation
As You can see first row is definitely too high. Probably the reason of that behavior is the fact, that I use text wrap in grid cells.
.x-grid-cell-inner { white-space: normal; }
Is there any efficient way to make grid rows, not to change their height after hiding columns (and using textwrap ) ?
I've personally encountered this strange phenomenon before. The problem is caused by Ext JS "hiding" columns by setting the width to 0px.
My solution was to add event listeners to the grid header like this:
// me is the grid
me.headerCt.on({
columnhide: me.removeWordWrapOnHide,
columnshow: me.addWordWrapOnShow,
scope: me
});
Instead of using the existing x-grid-cell-inner class, make a new one like this:
<style type="text/css">
td.grid-cell-wordwrap > div {
white-space: normal; /* may need !important, not sure */
}
</style>
Then the implementation of these two functions did this:
removeWordWrapOnHide: function(headerCt, column){
var me = this,
wordWrapRe = /wordwrap/;
if(column.useWordWrap || wordWrapRe.test(column.tdCls)){
column.tdCls = column.tdCls.replace("grid-cell-wordwrap", "");
column.useWordWrap = true; // Flag to check on show
me.view.refresh();
}
},
addWordWrapOnShow: function(headerCt, column){
var me = this,
wordWrapRe = /wordwrap/;
if(column.useWordWrap && !wordWrapRe.test(column.tdCls)){
column.tdCls = "grid-cell-wordwrap " + column.tdCls;
me.view.refresh();
}
}
Might not be the most efficient way, but it gets the job done.

Is it possible to change the position of generated <tr> by css?

Some asp.net controls generate , so to customize its appearance (e.g. childview in grid) i need to change the position of < tr> content. I don't know any ways to change position. The only idea is to generate div wrappers by javascript. Does anybody know a better way?
if you want to "move" the tr to another place, you can try:
<table>
<tr id="tr1"><td>test</td><td>test2</td></tr>
<tr id="tr2"><td>test3</td><td>test4</td></tr>
<tr id="tr3"><td>test4</td><td>test5</td></tr>
</body>
<script>
var tr = document.getElementById("tr2");
tr.style.display = 'block';
tr.style.position = 'absolute';
tr.style.top = "100px";
tr.style.left = "100px";
</script>
it definitely works in firefox (dont know about ie6-8). If you want to exchange the content with another tr, thats even easier (you just remove/add the tr nodes).

Autosize Text Area (Multiline asp:TextBox)

I have a MultiLine asp:Textbox (a standard html textarea for those non-asp people) that I want to be auto-sized to fit all it's content only through css. The reason for this is that I want it to be of a specified height in the web browser, with scrolling enabled.
I have implemented a print style sheet however and want all text located in the textarea to be displayed when printed with no overflow hidden.
I can manually specify the height of the textarea in the print.css file problem with this being that the fields are optional and a 350px blank box is not optimal and there is always the possibility of a larger amount of text than this...
I have tried using :
height: auto;
height: 100%;
In IE and Firefox respectively yet these seem to be overridden by the presence of a specified number of rows in the html mark-up for the form which must be generated by .NET when you do not specify a height on the asp:Textbox tag, this seems to only accept numercial measurements such as px em etc...
Any ideas?
What you are asking for (a css solution) is not possible.
The content of the textarea is not html elements, so it can not be used by css to calculate the size of the textarea.
The only thing that could work would be Javascript, e.g. reading the scrollHeight property and use that to set the height of the element. Still the scrollHeight property is non-standard, so it might not work in all browsers.
jQuery or a javascript function to find and make textboxes bigger might be the best solution - at least thats what i found
we use this set of functions and call clean form after the page is loaded (i know this isnt the best solution right here and am working to transfer to a jQuery solution that is more elegant) - one note make sure your textareas have rows and cols specified or it doesnt work right.
function countLines(strtocount, cols)
{
var hard_lines = 1;
var last = 0;
while (true)
{
last = strtocount.indexOf("\n", last + 1);
hard_lines++;
if (last == -1) break;
}
var soft_lines = Math.round(strtocount.length / (cols - 1));
var hard = eval("hard_lines " + unescape("%3e") + "soft_lines;");
if (hard) soft_lines = hard_lines; return soft_lines;
}
function cleanForm()
{
var the_form = document.forms[0];
for (var i = 0, il = the_form.length; i < il; i++)
{
if (!the_form[i]) continue;
if (typeof the_form[i].rows != "number") continue;
the_form[i].rows = countLines(the_form[i].value, the_form[i].cols) + 1;
}
setTimeout("cleanForm();", 3000);
}
If you set rows to be a ridiculously high number the CSS height rule should override it on the screen.
Then in the print stylesheet just set height to auto. This might result in some big blank space where all the available rows haven't been filled up, but at least all text will be visible.
give jQuery's autogrow() a go #
http://plugins.jquery.com/project/autogrow

Resources