Angular ng-grid row height - javascript

is there any way to apply the height of the row in ng-grid according to its content.
there is one option rowHeight which is changed the height of all row. But I want dynamic row height according to its content.
Following is the Plunker I have made, in this I have used cellTemplate to insert Education field, But I want to increase the row height according to education field detail.
http://plnkr.co/edit/tQJNpB?p=preview
According to this link it is not possible:
[1]https://github.com/angular-ui/ng-grid/issues/157
But if anyone find the solution.....

These classes will make the table act as actual table, using display table-row and table-cell.
.ngCell {
display : table-cell;
height: auto !important;
overflow:visible;
position: static;
}
.ngRow {
display : table-row;
height: auto !important;
position: static;
}
.ngCellText{
height: auto !important;
white-space: normal;
overflow:visible;
}
Please note that this is supported by IE8 and up. It's also overriding the entire ng grid classes so it will be wise to use on a "need to" base:
#myTableId .ngCell {...}
#myTableId .ngRow {...}
...

Researching this discovered that in my fix should call anonymous function $scope.resizeViewPort whenever it makes change to ngGrid data or should be called whenever the viewport rows are updated.
Examples are after angular performs updates to the rows via data from the ng-grid module. I've found these steps useful in my anonymous function for height only:
$scope.resizeViewPort = function { // and the two steps below
// retrieve viewPortHeight
var viewportHeight = $('ngViewPort').height();
var gridHeight = $('ngGrid').height();
// set the .ngGridStyle or the first parent of my ngViewPort in current scope
var viewportHeight = $('.ngViewport').height();
var canvasHeight = $('.ngCanvas').height();
var gridHeight = $('.ngGrid').height();
alert("vp:" + viewportHeight + " cv:" + canvasHeight + " gh:" + gridHeight);
var finalHeight = canvasHeight;
var minHeight = 150;
var maxHeight = 300;
// if the grid height less than 150 set to 150, same for > 300 set to 300
if (finalHeight < minHeight) {
finalHeight = minHeight;
} else if (finalHeight > viewportHeight) {
finalHeight = maxHeight;
}
$(".ngViewport").height(finalHeight);
}

I wanted to chime in on this question. I have followed up on this example and have used the solution provided by getuliojr. This solution seems to work pretty well, note that you will have to clone the fork and build the source in order to use in your app. I have a plunker live of it working: http://plnkr.co/edit/nhujNRyhET4NT04Mv6Mo?p=preview
Note you will also need to add 2 css rules:
.ngCellText{
white-space:normal !important;
}
.ngVerticalBarVisible{
height: 100% !important;
}
I have yet to test this under significant load or cross-browser but will update with more once I do.
GH Repo for ng-grid with flexible height by getuliojr: https://github.com/getuliojr/ng-grid/commits/master

None of these solutions will work completely. The height being fixed is assumed all through out the code. It is typical with row virtualization to assume this because you aren't loading up all the rows at once so its very difficult to tell the ultimate height of the grid. NGrid 3.0 is supposed to support dynamic row height but I'm not sure when it is expected to be ready.

Adapt-Strap. Here is the fiddle.
It is extremely lightweight and has dynamic row heights.
<ad-table-lite table-name="carsForSale"
column-definition="carsTableColumnDefinition"
local-data-source="models.carsForSale"
page-sizes="[7, 20]">
</ad-table-lite>

it's not the sexiest thing in the world and I doubt it's that performant but this does the trick:
function flexRowHeight() {
var self = this;
self.grid = null;
self.scope = null;
self.init = function (scope, grid, services) {
self.domUtilityService = services.DomUtilityService;
self.grid = grid;
self.scope = scope;
var adjust = function() {
setTimeout(function(){
var row = $(self.grid.$canvas).find('.ngRow'),
offs;
row.each(function(){
var mh = 0,
s = angular.element(this).scope();
$(this).find('> div').each(function(){
var h = $(this)[0].scrollHeight;
if(h > mh)
mh = h
$(this).css('height','100%');
});
$(this).height(mh)
if(offs)
$(this).css('top',offs + 'px');
offs = $(this).position().top + mh;
self.scope.$apply(function(){
s.rowHeight = mh;
});
});
},1);
}
self.scope.$watch(self.grid.config.data, adjust, true);
}
}
execute using plugins in options:
plugins: [new flexRowHeight()]

Related

Sticky block on JS

helloi want to make a sticky block using this script
$(window).scroll(function() {
var sb_m = 80; /* top and bottom padding */
var mb = 300; /* footer height with a margin */
var st = $(window).scrollTop();
var sb = $(".loginform");
var sbi = $(".loginform #loginform");
var sb_ot = sb.offset().top;
var sbi_ot = sbi.offset().top;
var sb_h = sb.height();
if(sb_h + $(document).scrollTop() + sb_m + mb < $(document).height()) {
if(st > sb_ot) {
var h = Math.round(st - sb_ot) + sb_m;
sb.css({"paddingTop" : h});
}
else {
sb.css({"paddingTop" : 0});
}
}
});
on naked HTML all work fine
if add a script to site (use wordpress) appears an infinite scroll
here can see problem
problem appears if add an element to footer through widgets
please tell me what is problem?
Honestly it's not ideal to work with padding-top, you should use top (with the element set as position:relative or absolute);
If you don't care about supporting IE, the easiest way is to use position:sticky; which does all the work for you: https://developer.mozilla.org/en-US/docs/Web/CSS/position
If you prefer to do it yourself, I'd suggest working this way:
store in variables the current offset().top and .left of the soon-to-be sticky element, outside any onScroll handlers.
When this condition is true:
$(window.scrollTop() >= theElementOffsetTopValueYouStored)
set the element as position: fixed and set the left: and top: properties of the element that should become sticky with the values you stored before. Then add your condition to make sure it stops when it reaches the end of the document, checking if element.offset().top + element.height > document.height
Please consider this is from memory, you might need to tweak a few things here and there to make it work properly.

How to auto resize the textarea to fit the content?

I'm trying to auto resize the textarea so it fits the content in it but I'm facing a stuttering issue after I click enter to proceed to the next line. How can I fix this?
This is what I'm trying to do, see the image below.
Please see this link for the StackBlitz example
CODE
this.form.valueChanges.subscribe(() => {
const textarea = this.myDiv.nativeElement;
textarea.addEventListener('keydown', function() {
setTimeout(() => {
this.style.cssText = 'height:auto; padding:0';
this.style.cssText = 'height:' + this.scrollHeight + 'px';
}, 0);
});
});
addEventListener here is redundant since valueChanges already notifies you when the field changes. Instead, update the height using the ViewChild reference myDiv.
this.myForm.valueChanges.subscribe(value => {
this.myDiv.nativeElement.style.height = 'auto';
this.myDiv.nativeElement.style.height = `${this.myDiv.nativeElement.scrollHeight}px`;
});
Then add overflow: hidden to your css so the scrollbar doesn't show.
textarea {
resize: horizontal;
overflow: hidden;
}
You can keep the resize: horizontal; but it is no longer required since the textarea will resize automatically anyway.
Here is a working example on StackBlitz.
For anyone still looking for an answer to this in almost 2021, it's covered in the official Angular Material docs here. Directly manipulating the DOM via nativeElement is an anti-pattern.
<mat-form-field [style.fontSize]="fontSize.value">
<mat-label>Autosize textarea</mat-label>
<textarea matInput
cdkTextareaAutosize
#autosize="cdkTextareaAutosize"
cdkAutosizeMinRows="1"
cdkAutosizeMaxRows="5"></textarea>
</mat-form-field>
What you are trying to achieve is a very old trick. I have used it myself but trying a different approach.
It makes more sense why the text area is jumpy coz every keystroke you were making the height = 0 to calculate scroll height so that you can assign a new height.
I calculated the fontSize or lineHeight and calculated number of lines and the initial height to adjust based on that. So on every keystroke you are just assigning height w/o making the text area height=0
textareaProps = null;
getHeight(element) {
const lines = element.value.split(/\r\n|\r|\n/).length;
if(!this.textareaProps) {
const autoStyle = getComputedStyle(element);
const lineHeight = parseInt(autoStyle.lineHeight);
const adjust = parseInt(autoStyle.height) - lineHeight;
this.textareaProps = {adjust, lineHeight}
}
const { adjust, lineHeight } = this.textareaProps;
const height = lines * lineHeight + adjust;
return height + 'px';
}
You now need to call this method to get height and pass the textarea element as arg.
element.style.cssText = 'height:' + getHeight(element) ;
Edit 2
Sadly the above solution will only work if there are line breaks by user. When you enter a huge line text area wraps it but it doesn't increase the height. So intruducing a proxy html element which will have the text as same as text area value and will provide a height that we can assign to our text area.
textareaProps = null;
getHeight(element) {
if(!this.textareaProps) {
const proxy = document.createElement('div');
const {padding, width, fontSize, height, lineHeight} = getComputedStyle(element);
const css = [
'position:absolute',
'visibility: hidden',
'pointer-events:none',
`width: ${width}`,
`padding:${padding}`,
`min-height: ${height}`,
`font-size:${fontSize}`,
`line-height:${lineHeight}`,
].join(';');
proxy.style.cssText=css;
this.textareaProps = {
proxy: document.body.appendChild(proxy),
adjust: (parseInt(fontSize))
};
}
const { proxy, adjust} = this.textareaProps;
proxy.innerText = element.value + '.';
return (proxy.offsetHeight + adjust) + 'px';
}
Updated StackBlitz https://stackblitz.com/edit/next-line-view-child-ssnp4q
<textarea rows="15" id="code" disabled placeholder="Description"></textarea>
rows="15" to set min heigth to 15 rows
el = document.getElementById("code");
el.style.height = "auto";
// code to populate textarea
el.style.height = (5 + el.scrollHeight) + "px";
this helped me to set textarea to height as per content populated in it.
If you dont want a plugin there is a very simple solution
$(document).ready(function() {
$('textarea').on('keyup keypress', function() {
$(this).height(0);
$(this).height(this.scrollHeight);
});
$("textarea").each(function(textarea) {
$(this).height(0);
$(this).height(this.scrollHeight);
});
});

Proportionally scale website to fit browser window

What would be an elegant solution to proportionally scale and center an entire website to fit a browser window (and updating as it's re-sized)
Assume the base layout is 720x500px
Content should proportionally scale to fit, and then re-center.
Essentially, operating like this Flash plugin: http://site-old.greensock.com/autofitarea/ (though base size is known)
Site will contain several different types of elements in that 720x500 area... ideal solution would just scale the whole thing, not needing to style each individual element (in case it matters- images will be SVG and so scaling should have no negative affect on resolution)
Depending on the browsers you need to support (IE9+), you could achieve that with simple CSS transform.
See an example (using jQuery) in this jsfiddle
var $win = $(window);
var $lay = $('#layout');
var baseSize = {
w: 720,
h: 500
}
function updateScale() {
var ww = $win.width();
var wh = $win.height();
var newScale = 1;
// compare ratios
if(ww/wh < baseSize.w/baseSize.h) { // tall ratio
newScale = ww / baseSize.w;
} else { // wide ratio
newScale = wh / baseSize.h;
}
$lay.css('transform', 'scale(' + newScale + ',' + newScale + ')');
console.log(newScale);
}
$(window).resize(updateScale);
If you need backwards compatibility, you could size everything in your site with % or em, and use a similar javascript to control the scale. I think that would be very laborious though.
One solution I'm using is working with a container in which I put an iframe that's being resized to fit as much available screen as possible without losing it's ratio. It works well but it's not completely flexible: you need to set dimensions in your content page in % if you want it to work. But if you can manage your page this way, I think it does pretty much what you want.
It goes like this. You create a container html page that's basically only styles, the resize script and the iframe call. And you content goes into the iframe page.
<style>
html, body
{
border: 0px;margin: 0px;
padding:0px;
}
iframe
{
display: block;
border: 0px;
margin: 0px auto;
padding:0px;
}
</style>
<script>
$(document).ready(function(e){
onResizeFn();
});
$(window).resize(function(e){
onResizeFn();
});
// this stretches the content iframe always either to max height or max width
function onResizeFn(){
var screen_ratio = 0.70 // this is your 720x500 ratio
if((window.innerHeight/window.innerWidth) > screen_ratio){
var theWidth = window.innerWidth
var theHeight = (window.innerWidth*screen_ratio);
} else {
var theHeight = window.innerHeight;
var theWidth = (window.innerHeight/screen_ratio);
}
document.getElementById("your_iframe").width = theWidth + "px"
document.getElementById("your_iframe").height = theHeight + "px"
}
</script>
// And then you call your page here
<iframe id='your_iframe' src='your_content_page' scrolling='no' frameborder='0'"></iframe>

Change tinyMce editor's height dynamically

I am using tinymce editor in my page. What I want to do is to change the height of the editor dynamically. I have created a function:
function setComposeTextareaHeight()
{
$("#compose").height(200);
}
but that is not working.
My textarea is
<textarea id="compose" cols="80" name="composeMailContent" style="width: 100%; height: 100%">
I have tried all sorts of methods for changing the height but could not come to a resolution. Is there any thing that i am missing?
You can resize tinymce with the resizeTo theme method:
editorinstance.theme.resizeTo (width, height);
The width and height set the new size of the editing area - I have not found a way to deduce the extra size of the editor instance, so you might want to do something like this:
editorinstance.theme.resizeTo (new_width - 2, new_height - 32);
Try:
tinyMCE.init({
mode : "exact",
elements : "elm1",
....
To change size dynamically in your javascript code:
var resizeHeight = 350;
var resizeWidth = 450;
tinyMCE.DOM.setStyle(tinyMCE.DOM.get("elm1" + '_ifr'), 'height', resizeHeight + 'px');
tinyMCE.DOM.setStyle(tinyMCE.DOM.get("elm1" + '_ifr'), 'width', resizeWidth + 'px');
The following comes in from this other SO answer I posted:
None of the above were working for me in TinyMCE v4, so my solution was to calculate the height based on the toolbars/menu bar/status bar, and then set the height of the editor, taking those heights into consideration.
function resizeEditor(myHeight) {
window.console.log('resizeEditor');
myEditor = getEditor();
if (myEditor) {
try {
if (!myHeight) {
var targetHeight = window.innerHeight; // Change this to the height of your wrapper element
var mce_bars_height = 0;
$('.mce-toolbar, .mce-statusbar, .mce-menubar').each(function(){
mce_bars_height += $(this).height();
});
window.console.log('mce bars height total: '+mce_bars_height);
myHeight = targetHeight - mce_bars_height - 8; // the extra 8 is for margin added between the toolbars
}
window.console.log('resizeEditor: ', myHeight);
myEditor.theme.resizeTo('100%', myHeight); // sets the dimensions of the editable area
}
catch (err) {
}
}
}
In my case, I wanted the editor window to match the width and height of the actual window, since the editor would come up in a popup. To detect changes and resize, I set this to a callback:
window.onresize = function() {
resizeEditor();
}
It's a bit late but for Googler like me, check the autoresize plugin
tinymce.init({
plugins: "autoresize"
});
Options
autoresize_min_height : Min height value of the editor when it auto resizes.
autoresize_max_height : Max height value of the editor when it auto resizes.
I'm using tinymce 4.8.3.
I display the editor in a resizable modal dialog box.
I solved this using flexbox, shown here in SASS/SCSS:
// TinyMCE editor is inside a container something like this
.html-container {
height: 100%;
overflow: hidden;
}
.mce-tinymce {
// This prevents the bottom border being clipped
// May work with just 100%, I may have interference with other styles
height: calc(100% - 2px);
& > .mce-container-body {
height: 100%;
display: flex;
flex-direction: column;
& > .mce-edit-area {
flex: 1;
// This somehow prevents minimum height of iframe in Chrome
// If we resize too small the iframe stops shrinking.
height: 1px;
}
}
}
When the editor is initialized we have to tell it to put 100% height on the IFRAME. In my case I also have to subtract 2px else the right border is clipped off:
tinymce.init({
...
height: "100%",
width: "calc(100% - 2px)"
});
What ManseUK stated is almost correct.
The correct solution is:
$('#compose_ifr').height(200);
or in your case
$('#composeMailContent_ifr').height(200);
Update: maybe this is more what you are looking for:
// resizes editoriframe
resizeIframe: function(frameid) {
var frameid = frameid ? frameid : this.editor.id+'_ifr';
var currentfr=document.getElementById(frameid);
if (currentfr && !window.opera){
currentfr.style.display="block";
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) { //ns6 syntax
currentfr.height = 200 + 26;
}
else if (currentfr.Document && currentfr.Document.body.scrollHeight) { //ie5+ syntax
currentfr.height = 200;
}
styles = currentfr.getAttribute('style').split(';');
for (var i=0; i<styles.length; i++) {
if ( styles[i].search('height:') ==1 ){
styles.splice(i,1);
break;
}
};
currentfr.setAttribute('style', styles.join(';'));
}
},
In case someone finds this and also wants to change the height of the source code editor plugin.
You need to edit the following file:
\tiny_mce\plugins\code\plugin.min.js
Look out for the attribute called minHeigh and adjust it to your needs. The height you define there is not the height of the entire box, but it is not the height of the textarea either. It is something inbetween.
You can set it according to your height
tinymce.init({
height: "500px"
});
I test this solution on version 5 of TinyMCE.
For change the height of TinyMCE after page loaded, all you need is: your element id
$(function(){
var selectedElement = tinymce.get('Element id without sharp(#)');
selectedElement.settings.height = 700;
selectedElement.settings.max_height = 400;
selectedElement.settings.min_height = 1000;
});
Also you can use autoresize plugin for get better experience:
tinymce.init({
plugins: 'wordcount autoresize',
})
$(window).load(function () {
$('#YourID_ifr').css('height', '550px');
});

Runtime error with footer's resizing using jQuery

I'm currently working with PHP, and this footer is one of the components of every page. First off, I know that a footer of this size needs to be made smaller before I publish it; it's currently formatted like this before I create drop-down (or in this case, pop-up) menus.
I currently have jQuery set to auto-resize the footer's height on window resize (with debounce), since the internal elements move in a grid pattern. However, I've run into a couple issues:
On the first page load, before any resizes, it doesn't extend the footer sufficiently far enough so all internal elements are on the same colored background. I know I could just add a constant, but I want it to scale with the end user's default text size.
After multiple resizes, the footer's total height is several times more than intended.
I can't spot the error; what am I doing wrong? I've pasted the relevant code into jsFiddle, as it's rather long.
Code (jsFiddle)
EDIT: Problem 2 fixed. Default behavior is now Problem 1.
EDIT 2: Here's a preview. You should still checkout the fiddle, though.
var maxWidth, maxHeight, numBoxes;
function arrangeFooter() {
// Get the width of the footer to determine # of rows
var footerWidth = $("#footer").width();
// Get list of .box divs' widths and lengths
var widths = $(".box").map(function() {
return $(this).innerWidth();
}).get();
var heights = $(".box").map(function() {
return $(this).height();
}).get();
numBoxes = widths.length;
// Find maxWidth, maxHeight of .box divs
// From these, finds # of cols that can fit with the maxWidth,
// and number of rows
maxWidth = Math.max.apply(Math, widths);
maxHeight = Math.max.apply(Math, heights);
var cols = Math.floor(footerWidth / maxWidth);
var rows = Math.ceil(numBoxes / cols);
// Calculates footer's new height, defined as
// maxHeight * num rows + height of .firstrow div
var newHeight = maxHeight * rows + parseFloat($(".firstrow").css("font-size"));
// Prints out resulting CSS rules directly to page
var styling = "\n .box {\n height: " + maxHeight + "px;\n width: " +
maxWidth + "px;\n }\n"
styling += "\n #footer {\n height:" + newHeight + "px;\n }\n";
$("#style").text(styling);
}
function resizeFooter() {
var footerWidth = $("#footer").width();
var cols = Math.floor(footerWidth / maxWidth);
var rows = Math.ceil(numBoxes / cols);
// Calculates footer's new height, defined as
// maxHeight * num rows + height of .firstrow div
var newHeight = maxHeight * rows + parseFloat($(".firstrow").css("font-size"));
// Prints out resulting CSS rules directly to page
$('#footer').css('height',newHeight);
}
// Debounce method; used to ensure that only one event is fired
// after ms if multiple identical events are triggered
var delay = (function() {
var timers = {};
return function(callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout(timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
function init() {
// calls arrangeFooter after 200ms to ensure page loads first
setTimeout(arrangeFooter, 200);
// Problem? Executes 500ms after window resize is "complete"
$(window).on("resize", function() {
delay(function() {
resizeFooter();
}, 500, "resize");
});
}
window.onload = init();​
After messing with the code a bit I think the problem is related to adding the font size of the first row to the size of the content in the box div.
This will add about 16 pixels to the height, but won't add the margin (10 pixels), padding (another 10 pixels) or border (1 pixel). Furthermore if the screen is so thin that for some reason that row extends to two lines then it'll only add the font-size once and not twice.
Therefore I propose the alternative:
var newHeight = maxHeight * rows + $(".firstrow").outerHeight(true);
.outerHeight(true) will give you the height of the element including margins.

Categories

Resources