Add borders around a flexible handsontable - css

I want to make a handsontable starting from 1 single cell. Then we can add/remove rows/columns by the contexte menu, or even copy-paste data from an Excel file. I fixe the maximum size to be 104 x 66. So if there are many data, the handsontable will have scrolling.
Now, I want to add borders around the table, for all the cases: 1) when the table does not reach its maximum size, the borders should be JUST around the cells; 2) when the table reaches its maximum size, the borders should be around the maximum size. I have made this JSBin, which satisfies the second case, but NOT the first one:
<!DOCTYPE html>
<html>
<head>
<script src="https://docs.handsontable.com/pro/1.9.1/bower_components/handsontable-pro/dist/handsontable.full.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://docs.handsontable.com/pro/1.9.1/bower_components/handsontable-pro/dist/handsontable.full.min.css">
<style>
.handsontable { border: 1px solid red; }
</style>
</head>
<body>
<div id="example4" class="hot head-gap handsontable htRowHeaders htColumnHeaders"></div>
</body>
</html>
JavaScript:
document.addEventListener("DOMContentLoaded", function() {
function getData() {
return [
[""]
];
}
var
example4 = document.getElementById('example4'),
hot4;
hot4 = new Handsontable(example4, {
data: getData(),
width: 104,
height: 66,
colWidths: 47,
rowHeights: 23,
rowHeaders: false,
colHeaders: false,
contextMenu: true,
contextMenuCopyPaste: {
swfPath: '/bower_components/zeroclipboard/dist/ZeroClipboard.swf'
}
});
});
Does anyone have a solution?
Edit 1: Following the answer of Serg Chernata:
Edit 2: Following the answer of fap, I see two problems:
1) the red borders are even around the context menu:
2) the red borders are outside the blue borders of the data:

I have kinda added some thing and posted in JSBin. I have added css and included jquery to your original html for dom related queries. Do let me know whether it helps. Here is the JS code.
document.addEventListener("DOMContentLoaded", function() {
function getData() {
return [
[""]
];
}
var
example4 = document.getElementById('example4'),
hot4;
hot4 = new Handsontable(example4, {
data: getData(),
width: 104,
height: 66,
colWidths: 47,
rowHeights: 23,
rowHeaders: false,
colHeaders: false,
contextMenu: true,
contextMenuCopyPaste: {
swfPath: '/bower_components/zeroclipboard/dist/ZeroClipboard.swf'
},
afterRender: function() {
var item = $('.ht_master.handsontable .wtHolder')[0];
if (item.scrollHeight > item.clientHeight || item.scrollWidth > item.clientWidth) {
$('.handsontable').css('border', '1px solid red');
$(item).find('.htCore').css('border', '0px none white');
} else {
$(item).find('.htCore').css('border', '1px solid red');
}
}
});
});

Assuming I understood your requirements correctly, we can probably do this with a little bit of css:
#example4{
max-width: 104px;
max-height: 66px;
display: inline-block;
}
Note, I removed the width and height from your dandsontable config. This way we can scale with content up to a certain defined max-width and max-height.
http://jsbin.com/qehexiyidu/edit?html,css,js,output

I have a solution that, I believe, cover all your requirments by using the after create/remove col/row events, but it's not perfect.
What I did is changing dynamically the Width and Height of the table after one of the events, e.g :
hot4.addHook('afterCreateCol', function() {
setTable();
});
If one of or both value are above the limit, they will stay at this limit. (104 x 66 in your example)
So the main function would be :
function setTable() {
if(hot4.getColWidth()*hot4.countCols()<208)
hot4.updateSettings({
width: hot4.getColWidth()*hot4.countCols()
});
else
hot4.updateSettings({
width: 208
});
if(hot4.getRowHeight()*hot4.countRows()<132)
hot4.updateSettings({
height: hot4.getRowHeight()*hot4.countRows()
});
else
hot4.updateSettings({
height: 132
});
}
(I used 208 x 132 for my eyes..)
Note that I load the data after the creation of the table to trigger the event afterLoadData.
The only remaining "issue" (I said it wasn't perfect..) would be the scrollbars. I don't know why, but even if the data fits, the scrollbar are present under the limit. It's supposed to be fixed, but apparently not... (I'm very interested if you manage to fix this)
Anyway, I think that starting from this solution, you may succeed to reach exactly what you want so I decided to share it with you in it's current state. You can find a working example in this JSBin.
Edit 1 : Screenshot of the "Scrollbars issue"
Even if the 2x2 cells fit in the table, the scrollbars are present.

Related

Anyone have solutions for table>th with position:sticky not working on FF & IE?

I have an idea to make sticky header of table and I have tried with position:sticky. It's
working fine on Chrome but on Firefox and IE not working as I think. Below is my CSS
.myTable--mof thead th {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index:100;
}
position:sticky is not supported for child table elements in some browsers. The 'why' I don't know.. Will it be supported in the future? I sure hope so!
I recently wrote this jQuery solution. It'll work for simple tables with simple headers. Does not look for colspans or multiple rows in thead!
I tried some plugins before, but they all listened for the scroll event which throws alerts in some browsers. They caused flickering/jumping in some cases, and a delay was noticable when hitting the position to stick at.
Using position:sticky for other elements and liking those transitions more, I came up with the following piece of code.
jQuery.fn.stickTableHeaders = function() {
return this.each(function()
{
var table = $(this),
header = table.find('thead'),
sticked = $('<table></table>').addClass('table').append(header.clone()); // Needs to be wrapped in new table since table child elements can't be sticky? (FF)
sticked.find('th').css({ // You'll have to copy the original thead (th's) CSS manualy
'backgroundColor': '#DEE5EA',
'color': '#606060',
'padding':'8px',
'color':'#606060'
}).removeAttr('width'); // And remove the width attr from the clone th's since we'll be setting them again later
sticked.find('th:not(:last-child)').css({ // More CSS
'borderRight': '1px solid #ddd'
});
sticked.find('a').css({ // More CSS
'color':'#606060'
});
// I tried different things, most of the original th's should have a width attribute set (not in CSS and avoid percent) for best results
$(window).resize(function() {
sticked.width(table.width());
sticked.find('th').each(function() {
var headerTH = header.find('th').eq($(this).index());
if(headerTH.is('[width]') || headerTH.is(':first-child') || headerTH.is(':last-child')) { // First and last th are allready calculated by another function in my app. See what suits for you here...
$(this).width(header.find('th').eq($(this).index()).width());
}
else {
var cellWidth = header.find('th').eq($(this).index()).width(true),
tableWidth = table.width(true),
percent = 100*(cellWidth/tableWidth);
$(this).css({'width':percent+'%'});
}
});
// We keep the original thead to avoid table collapsing, we just slide the whole table up.
table.css({
'marginTop':-header.height()
});
}).trigger('resize');
// Apply stickyness
sticked.css({
'display':'table',
'position':'sticky',
'top':$('#header-menu').height(), // My sticky nav is my top position, adjust this to your needs
'zIndex':'10'
});
// Insert clone before original table
$(this).before(sticked);
});
};
Now I just use this on each page load:
$("table").stickTableHeaders();
You might want to filter out nested tables from the above selector...
Hope this helps someone.

ExtJS 4 - Show LoadMask without spinner image

This should probably be pretty straighforward but I haven't been able to figure it out. I'm just trying to show a loadmask on a component without the spinner image. Everything else I want to look exactly the same.
I've set up a jsfiddle with a regular loadmask applied. Again, just trying to figure out how to exclude the spinner image.
Ext.onReady(function () {
Ext.create('Ext.window.Window', {
height: 500,
width: 500,
autoShow: true,
title: 'Loadmask example',
html: 'adsfa',
listeners: {
boxready: function (win) {
var lm = new Ext.LoadMask(win, {
msg: 'loadmask msg'
});
lm.show();
}
}
});
});
jsfiddle
Add a custom css class to the LoadMask object. You need to override background of this class.
.custom-mask .x-mask-msg-text {
background: transparent !important;
padding: 5px !important
}
Demo

How to set up twitter's embedded timeline width in percentage (responsive/fluid design)

I'm looking to set up twitter's embedded timeline, it's quite easy when you're having a fixed design, but that's not my case and I'm actually building a fluid and responsive design for a new website.
My question is, how can I set up twitter's embedded timeline with a fluid width since its an iframe and you're supposed to set up the with in px in your twitter account ?
Thanks :)
This seems to work for me:
#twitter-widget-0 {
width:100%;
}
where #twitter-widget-0 is the iframe it generates, placed in an appropriately-styled container.
It's not perfect: the widget generates its contents a bit differently depending on width, and margins, etc. won't be exactly the same after resizing; but this seems minor.
I'm curious as to why simple CSS didn't work for you - sorry if I'm missing something.
Thanks to all of you I found my way through:
It was almost as lack said, but we had to focus on the iframe instead:
.MyClassForTheDivThatContainTheiFrame iframe{
width:100%;
}
of course .MyClassForTheDivThatContainTheiFrame is also fluid with a % width
This logic will work to change at least the width and height:
#twitter-widget-0, #twitter-widget-1 {
float: none;
width: 100% !important;
height: 250px !important;
}
The only problem with shortening the height is that it hides the text box for people to send tweets but it does shorten the height. My guess is that if you want to add other CSS styling you can just put the !important clause. I also assume that if you have three widgets you would define #twitter-widget-2, etc.
Super hacky, but you can also do this :
<script type="text/javascript">
var checkTwitterResize = 0;
function resizeTwitterWidget() {
if ($('#twitter-widget-0').length > 0) {
checkTwitterResize++;
if ($('#twitter-widget-0').attr('width') != '100%') checkTwitterResize = 0;
$('#twitter-widget-0').attr('width', '100%');
// Ensures it's checked at least 10 times (script runs after initial resize)
if (checkTwitterResize < 10) setTimeout('resizeTwitterWidget()', 50);
} else setTimeout('resizeTwitterWidget()', 50);
}
resizeTwitterWidget();
</script>
This was a helpful thread, thanks. I'm working on a site that uses an older Twitter profile Widget, which I find easier to customise. So an alternative method, uses this to display the feed (customised to suit):
<script>
new TWTR.Widget({
version: 2,
type: 'profile',
rpp: 5,
interval: 6000,
width: 300,
height: 400,
theme: {
shell: {
background: 'transparent',
color: '#151515'
},
tweets: {
background: 'transparent',
color: '#151515',
links: '#007dba'
}
},
features: {
shell: false,
scrollbar: true,
loop: false,
live: true,
hashtags: true,
timestamp: true,
avatars: true,
behavior: 'all'
}
}).render().setUser('BlueLevel').start();
</script>
Then override the width by adding this to your stylesheet:
.twtr-doc {
width:100% !important;
}
You can see the various classes to modify by using IE9 in compatibility mode, then using F12 Developer Tools to see the html/css.
Hope that helps someone!
You can give your iframe a class, and try to apply CSS to it. At least to change the width to %.
This is not possible. You can set an exact width and height using the html width and height in the anchor tab. Other than that you are out of luck. No responsive or fluid capabilities.
It also has a min-width of 220px and a max-width of 520px.
<a class="twitter-timeline" width="520" height="700" data-dnt=true href="https://twitter.com/vertmob" data-widget-id="WIDGET_ID_HERE">Tweets by #vertmob</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
If you absolutely must do a fluid, you can code a javascript that changes that iframe's width after a resize event or using some javascript timers.
Can we see some code of yours to make some js code for this?
Attribute selector should work:
iframe[id*="twitter-widget"] {
width: 100%;
}
More here.

Auto-resize an image in CSS without replacing HTML width / height attributes?

I'm trying to make an image fit nicely on different screen sizes without breaking the layout. The following bit of CSS helps:
.viewer .main img {
max-width: 100%;
height: auto;
}
But the trouble is this image changes. I use a bit of Javascript to create a new img element each time the image changes, instead of reusing the existing one. (This seems a little more reliable for what I'm doing). The browser doesn't know the image's size until it is loaded, creating an obvious flicker in the interim. I deal with that by setting the image's width and height attributes in HTML. Without the above CSS rule, that works fine.
With that CSS, the flickering is still there. For some reason, when I create a new img element, the CSS seems to be causing the browser to ignore its width and height attributes, so. It ends up as ignorant of the aspect ratio as it was before.
Here's a jsfiddle to illustrate the situation:
http://jsfiddle.net/7sDtN/
One of the images in there is very very big (138 MB), so be careful if you're on a metered connection :)
What I would love is to get the image to scale according to those dimensions I set in HTML. Preferably in a nice way. A Javascript solution isn't the end of the world (I'm already using it, for course), but if there's an elegant CSS solution that would be very nice.
I ended up solving this in a roundabout way by wrapping the image in a dedicated container, along with some strange looking javascript to keep it in place as the image loads. The dimensions for that container are calculated as in Sven's answer, but ultimately it lets the browser take over. This way layout changes are kept fairly minimal and we end up only doing this crazy stuff for the bit of time between images.
Here's a big wad of code, for completedness:
function Viewer(container) {
var viewer = this;
container = $(container);
var pictureBox = $('.picture', container);
var img = $('<img>').appendTo(pictureBox);
var hide = function() {
/* [snip] */
}
var getPictureDisplayHeight = function(picture) {
var ratio = picture.data.h / picture.data.w;
var displayWidth = Math.min(pictureBox.width(), picture.data.w);
var displayHeight = Math.min(displayWidth * ratio, picture.data.h);
return displayHeight;
}
var stopLoadingTimeoutId = undefined;
var stopLoadingTimeout = function() {
container.removeClass('loading');
}
var showPicture = function(picture) {
var imgIsChanging = img.data('picture') != picture;
container.show();
/* This code expects to be cleaned up by stopLoadingTimeout or onImgLoaded, which will not fire if img src doesn't change */
if (imgIsChanging) {
container.addClass('loading');
window.clearTimeout(stopLoadingTimeoutId);
stopLoadingTimeoutId = window.setTimeout(stopLoadingTimeout, 3000);
}
pictureBox.css({
'min-height' : pictureBox.height()
});
var displayHeight = getPictureDisplayHeight(picture);
if (displayHeight > pictureBox.height()) {
/* Grow pictureBox if necessary */
pictureBox.stop(true, false);
pictureBox.animate({
'height' : displayHeight
}, 150);
}
/* I wish I could set width and height here, but it causes the current image to stretch */
img.attr({
'src' : picture.fullPath
}).data('picture', picture);
}
var onImgLoaded = function(event) {
/* The load event might not be fired, so nothing here should be essential */
var picture = img.data('picture');
container.removeClass('loading');
var displayHeight = getPictureDisplayHeight(picture);
pictureBox.stop(true, false);
pictureBox.animate({
'min-height' : 0,
'height' : displayHeight
}, 150, function() {
pictureBox.css('height', 'auto');
});
window.clearTimeout(stopLoadingTimeoutId);
}
var onImgClicked = function(event) {
selectNextPicture();
}
var onPictureSelectedCb = function(picture) {
if (picture) {
showPicture(picture);
} else {
hide();
}
}
var init = function() {
img.on('click', onImgClicked);
img.on('load', onImgLoaded);
}
init();
}
Relevant HTML:
<div class="viewer" style="display: none;">
<div class="picture"></div>
<div class="caption"><div class="caption-text"></div></div>
</div>
And CSS:
.viewer .picture img {
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
This way we leave space around the image that is either the size of the next image or the size of the current image, and never the smaller size that seems to happen before a new image is loaded (which kept happening for some reason). There are probably a million solutions to this, and mine doesn't feel especially straight-forward, so I'm certainly curious to see others :)
If I understand you right, you can achieve your goal by using the following code
HTML
<div id="Wrapper">
<img id="MyPic" src="http://www.davidstorey.tv/wp-content/uploads/2012/05/image.php_.jpeg" alt="" width="300" height="200" />
</div>
CSS
body{
width:100%;
}
#Wrapper{
width:98%;
border:1px solid red;
}
jQuery
$("document").ready(function(){
var ratio=$("#MyPic").width() / $("#MyPic").height();
$("#MyPic").css("width","100%");
$("#MyPic").css("height", $("#MyPic").width()/ratio+"px");
});
Here is the link to jsfiddle

css width interval

Ok, here's a problem I've never run into before. I would like to use CSS to specify that an elements width should always be in 10 pixel intervals. So, for example, if the width of an element is 11, it would get bumped up to 20, 56 => 60, 138 => 140, etc...
I doubt CSS has a way to do this but thought I'd ask anyway. Something like this would be nice:
div { width-interval: 10px; }
The problem with this is that block-level elements are always the size of the window unless you specify otherwise. Once you specify a more specific width, you don't need a width inverval.
The two cases this would be different are;
If the block level element is shrink wrapped (in the case of floats and inline-blocks)
If the element has a relative width, ie a percentage.
But if you are setting it to be relative, you wouldn't need intervals, because it's supposed to be relative to other things on the page, so that would get complicated when other things had to be adjusted to compensate. For instance, if I had two divs:
<div id="one"></div>
<div id="two"></div>
and a rule:
#one {
width: 50%;
width-interval: 25px;
}
#two {
width: 50%;
width-interval: 27px;
}
Which one wins? If it's important for lining up pictures or text, you probably don't want either to trump the other, but it can't ignore both.
I think the idea is good, but would probably be better handled by javascript, since you are requiring it to be both dynamic and based on the "nearest" interval. This could work:
$(function () {
$(div).each(function() {
var cur_width = $(this).width();
var inverval_diff = cur_width % 10;
$(this).width(cur_width + inverval_diff);
});
});
The above is in jquery, in case you don't use that as your js framework.
css doesn't have such property, but you are able to style width of elements with additional JavaScript such as:
<script type="text/javascript">
$(function(){
var widthInterval = 20;
$('div').each(function(){
var $this = $(this);
var divisions = parseInt($this.width() / widthInterval) + 1;
var resWidth = (divisions * widthInterval) + "px";
$this.css('width', resWidth);
console.log("Resulted width: " + resWidth);
});
});
</script>
Hope it helps.

Resources