Have div width match that of the contents - javascript

I have a container div that holds a react handsontable component, and I want to use the autosizing of the component but at the same time have it centered in the screen (or an outer div).
So in this example:
https://jsfiddle.net/opike99/b1ux0rLy/5/
I'm trying to get the width of div #example1 to match the contents of the table (so by changing the number of columns, the div width will adjust accordingly).
HTML:
<script src="https://cdn.jsdelivr.net/npm/handsontable#11.1/dist/handsontable.full.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable#11.1/dist/handsontable.full.min.css" />
<script src="https://handsontable.com/docs/8.3.2/components/numbro/dist/languages.min.js"></script>
<div class="outer2">
<div class="outer1">
<div id="example1">
</div>
</div>
</div>
JS:
const container = document.querySelector('#example1');
const numberOfColumns = 7;
const hot = new Handsontable(container, {
data: Handsontable.helper.createSpreadsheetData(5, numberOfColumns),
colHeaders: true,
rowHeaders: true,
hiddenColumns: true,
width: 'auto',
height: 'auto',
licenseKey: 'non-commercial-and-evaluation',
});
// re-render your Handsontable instance
hot.render()
CSS:
.outer2 {
}
.outer1 {
}
#example1 {
border-style: solid;
/* width: fit-content; */
}

So I've been playing around with your example, and got the following results:
There's actually three tings you need to do:
The generated $('.wtHolder') has a width: 680px defined on a style attribute, so the only way to remove it is programatically.
$('.ht_master.handsontable, #example1') need width: fit-content
Using a flexbox, I was able to centre the table. I set display: flex; justify-content: center; on $('.outer1').
And for some reason, the order in which these are applied is important too. I got it working with a setTimeout, although you'd probably want something more sophisticated.
setTimeout(function() {
document.querySelector('.wtHolder').style.width = 'initial';
document.querySelector('#example1').style.width = 'fit-content';
const outer = document.querySelector('.outer1');
outer.style.display = 'flex';
outer.style.justifyContent = 'center';
}, 2000);
Let me know how you go.

Related

How to prevent angular component to scroll page instead of table?

I have this page like image below:
The filter has a dynamic width and is an external angular component
the table is inside the "parent" component
FYI:
The table component has a [height]="something" that accepts either string or number as parameters.
The table is a pivot table using a custom component called Dev-Extreme
All i want is to assign a value inside the [height]="" in the HTML component page that is dynamic so that the height of the table resizes based on how much space there is left in the page.
Could also use TypeScript to do that and maybe calculate the height each components takes in the page except the table and do calculations on that.
Can anyone help me here, i've been stuck on this for two hours.
You could use some css for what you need.
Use display: flex to distribute the sections as you need (top section fixed and bottom section with dynamic height).
And use overflow: auto to set the scroll in the table container only.
Example:
https://codepen.io/bcngr/pen/wvXdWBE
<div class="main">
<div class="filters-container">
<span>Filters</span>
</div>
<div class="table-container">
<div class="table">
<span>Table</span>
</div>
</div>
</div>
html, body {
padding: 0;
margin: 0;
}
.main {
height: 100vh;
display: flex;
flex-direction: column;
}
.filters-container {
background-color: #edf2f4;
height: 100px;
}
.table-container {
flex: 1;
overflow: auto;
}
.table {
background-image: linear-gradient(#8d99ae, #2b2d42);
height: 600px
}
I found a solution to this here's what i did:
Creating a #ViewChild() to gather the div element in my .ts:
#ViewChild('pivotFilter', { static: false }) stickyHeader?: ElementRef;
Here:
The div has an id="pivotFilter"
Using ViewChild we can get the HTML element
Declaring getter to calculate table height:
get filterHeight() { return window.innerHeight - (this.stickyHeader?.nativeElement.offsetHeight + 88); }
Here:
window.innerHeight is the height of the page
this.stickyHeader?.nativeElement.offsetHeight is the height of my component
That + 88 is the rest of the page height (the title, and the space between filter and table)
I had to run change detection on content initialization to prevent errors like so:
ngAfterContentInit(): void {
this.cd.detectChanges();
}
Then i just applied the height to the html page.
Hope this helps someone, cheers !

Trix editor define custom attachment styles

I added an image to the Trix editor, generating the following code:
<figure
data-trix-attachment="{lots of data}"
data-trix-content-type="image/jpeg"
data-trix-attributes="{'presentation':'gallery'}"
class="attachment attachment--preview attachment--jpg">
<img src="http://myhost/myimage.jpg" width="5731" height="3821">
<figcaption class="attachment__caption">
<span class="attachment__name">cool.jpg</span> <span class="attachment__size">4.1 MB</span>
</figcaption>
</figure>
When I display the generated HTML from the editor on my Bootstrap-based page, the image obviously extends the screen (see the width and height) and I'd like to remove these props and also assign the img-fluid class to it.
So basically I thought to use the config:
Trix.config.css.attachment = 'img-fluid'
But that does a) not change the attachment class to img-fluid and it also would not apply the changes to the image but the figure.
I would like to avoid using jQuery each time I display the content and traverse all figures and then manipulate the image's properties at runtime.
Isn't there a solution to define these styles when adding the attachment?
Trix does not have any kind of support to change the image element inside the attachment. One way to do it is by using MutationObserver to check for mutations inside Trix editor that apply to attributes, childList and subtree.
If we have a width or height attributes mutation to an img target node with a figure parent node, then we remove those attributes and we can apply the class img-fluid to the first attribute mutation, for example width.
Run code snippet and try to add some image attachments to see or inspect the HTML
Please read inline comments
// Listen to trix-attachment-add event so we'll get rid of the progress bar just for this demo
// Here we should upload the attachment and handle progress properly
document.addEventListener("trix-attachment-add", event => {
const { attachment } = event.attachment;
// Get rid of the progress bar
attachment.setUploadProgress(100)
});
// Get the Trix editor
const editor = document.querySelector('trix-editor');
// Instantiating an observer
const observer = new MutationObserver(function (mutations) {
mutations.forEach(({ type, target, attributeName }) => {
// If the parent is a figure with an img target
if (target.parentNode.tagName === 'FIGURE' &&
target.nodeName === 'IMG')
{
if (type === 'attributes') {
switch(attributeName) {
// If we have attribute width
case 'width':
// Remove attribute width
target.removeAttribute('width');
// Add img-fluid only once
target.classList.add('img-fluid');
break;
// If we have attribute height
case 'height':
// Remove attribute height
target.removeAttribute('height');
break;
}
}
// Render images HTML code
renderHtmlOutput();
}
});
});
// Observing Trix Editor
observer.observe(editor, {
attributes: true,
childList: true,
subtree: true
});
// Function to render every figure > img HTML code
function renderHtmlOutput() {
const images = editor.querySelectorAll('figure > img');
let output = '';
for(const image of images) {
output += image.outerHTML.replace(/ /g, "\n ") + "\n";
}
document.getElementById('output-html').textContent = output;
}
body {
height: 100vh;
margin: 0;
flex-direction: column;
display: flex;
}
#main {
display: flex;
flex-direction: row;
flex: 1;
margin: 10px;
}
#editor-container {
flex: 3;
}
#output-container {
flex: 2;
margin-left: 20px;
border-left: 1px solid lightgray;
overflow: auto;
}
#output-html {
margin: 0;
padding: 10px;
font-size: small;
color: blue;
}
/* Hide some Trix buttons to free horizontal space */
.trix-button--icon-increase-nesting-level,
.trix-button--icon-decrease-nesting-level,
.trix-button--icon-bullet-list,
.trix-button--icon-number-list { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.js" integrity="sha256-2D+ZJyeHHlEMmtuQTVtXt1gl0zRLKr51OCxyFfmFIBM=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.css" integrity="sha256-yebzx8LjuetQ3l4hhQ5eNaOxVLgqaY1y8JcrXuJrAOg=" crossorigin="anonymous"/>
<section id="main">
<div id="editor-container">
<form>
<input id="editor" value="Editor content goes here" type="hidden" name="content">
<trix-editor input="editor"></trix-editor>
</form>
</div>
<div id="output-container">
<pre id="output-html"></pre>
</div>
</section>

Div height doesn't get recalculated on resize

It works perfectly when I refresh the page, but when I resize it doesn't recalculate the div height.
JSFIDDLE
$(document).ready(function() {
var selectorsArray = ['home', 'about', 'portfolio', 'contact'];
responsiveResize(selectorsArray);
$(window).resize(function(){
var selectorsArray = ['home', 'about', 'portfolio', 'contact'];
responsiveResize(selectorsArray);
});
});
function responsiveResize(selectorsArray){
$.each(selectorsArray, function( index, value ) {
var cntcnter = $('#'+value+' .content-container');
var height = $('#'+value+' .content-container').height();
console.log(height);
cntcnter.css({'height': height+'px', 'margin-top': '-'+(height/2) +'px'});
});
}
The reason it's not working is because on the first run, you set a height to the container. On the second run, it already has a height set so it's always the same value. If the text overflows the container, it's not affecting the new height in this case.
If you want to keep using your code, you need to clear/remove the height you added on the previous run.
You can use this
var height = $('#'+value+' .content-container').css('height', '').height();
Like Chris Empx mentioned, this is easily obtainable with CSS.
Also, you could optimize the code like this fiddle
i wonder why you want to do that with jquery.
i would do that in css.
like that
<div class='container'>
<div class='column col 12'>
<p>Your Inputs here</p>
</div>
<div class='clear'></div>
</div>
then this in css
.container {
margin: 0 auto;
width: 960px;
}
.col-12{
width: 100%;
}
.clear {clear: both;}
.column {padding: 0 .8em; float:left;}
col-6 would be width:50%
col-3 would be width:25%

image background onclick

I am attempting to create a function where by a button is clicked and the background image is selected for a div. Here is what I have started below but it does not seem to work can anyone point out where Im going wrong... :)
<style type="text/css">
#txt{
width: auto;
height: auto;
border: solid #000;
}
</style>
<script type="text/javascript">
function backg1(){
var test = new string ();
test = document.getElementById('txt');
test.style.backgroundImage="url('cloud.jpg')";
}
</script>
</head>
<body>
<div id="txt">
<input type="button" value="BG1" onclick="backg1()"/>
</div>
Since your <div> originally contains nothing but the button input, it has no size outside the boundaries of that button. You will need to set an explicit width and height (along with position: relative) to see the background.
I would recommend setting them to the same dimensions as your image.
/* in the CSS */
#txt{
/* use the width, height of your image */
width: 400px;
height: 250px;
position: relative;
border: solid #000;
}
Or if you need to set them dynamically:
function backg1() {
test = document.getElementById('txt');
test.style.backgroundImage="url('cloud.jpg')";
// <div> needs a width & height for the background image to be visible outside the
// bounds of the one element contained in the div.
test.style.width = "400px";
test.style.height = "250px";
test.style.position = "relative";
}
There is a javascript error at this line.
var test = new string ();
You can make it like var test = new String(); Then it should work.
Moreover, i observed that you are creating string object and then you are overriding with DOM object. Not sure why it so like that. You can just create a variable like var test;

How do I set the containment on a jQuery UI Dialog?

Is it possible to add containment (confining to the boundary of another element) to jQuery UI's Dialog?
#Mottie's on the right track, but there's a simpler and better solution:
var container = $('.dialog-container'),
dialog = $('.ui-dialog');
dialog.draggable( "option", "containment", container );
Unlike Mottie's solution, this will not break if the viewport resizes. I've forked the JSFiddle here.
#Mac's on the right track, but the solution is not complete. You must also set the containment of the dialog's Resizable widget. If you only set the Draggable, you'll get containment when you drag, but when you grab the edges and resize you'll still go out of bounds.
So you'll want to do this, assuming #mydialog is the element you initially created the dialog from, and #boundary is the element you wish to confine it to (by the way, the container parameter can also be a selector):
let ui = $('#mydialog').closest('.ui-dialog'); // get parent frame
ui.draggable('option', 'containment', '#boundary'); // <-- drag, but not resize
ui.resizable('option', 'containment', '#boundary'); // <-- don't forget!!!
Here's an example snippet, toggle the checkboxes to switch the corresponding widget's confinement between 'document' (the default), and '#area'. Then experiment both with dragging the dialog by its title bar, and resizing it by its edges. Note what happens when you only select "Confine drag":
// Create dialog from #win with mostly default options.
$('#win').dialog({
width: 200,
height: 150,
position: { my: 'center', at: 'center', of: '#area' }
});
// When checkbox changed, update confinement settings.
$('#draggable, #resizable').change(function () {
let d = $('#draggable').prop('checked');
let r = $('#resizable').prop('checked');
let ui = $('#win').closest('.ui-dialog');
ui.draggable('option', 'containment', d ? '#area' : 'document');
ui.resizable('option', 'containment', r ? '#area' : 'document');
});
#area {
position: relative;
left: 2ex;
top: 2ex;
width: 400px;
height: 300px;
border: 1px solid red;
}
#win {
font-size: 10pt;
display: flex;
flex-direction: column;
}
label {
display: flex;
align-items: center;
}
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<div>Example</div>
<div id="area"></div>
<div id="win" title="test">
<label><input type="checkbox" id="draggable">Contain drag</label>
<label><input type="checkbox" id="resizable">Contain resize</label>
</div>
</body>
You could target the dialog box and apply a containment to it. Try this:
var container = $('.dialog-container'),
dialog = $('.ui-dialog');
// get container top left corner locations
var cx1 = container.offset().left,
cy1 = container.offset().top;
// get dialog size
var dw = dialog.outerWidth(),
dh = dialog.outerHeight();
// get container bottom right location, then subtract the dialog size
var cx2 = container.width() + cx1 - dw,
cy2 = container.height() + cy1 - dh;
dialog.draggable( "option", "containment", [cx1, cy1, cx2, cy2] );
Edit: I set up a demo for you.
Edit2: Changed to use dialog outerWidth & outerHeight

Categories

Resources