Getting correct height of an app part after removing item from repeat - angularjs

I'm building an app part in sharepoint (o365) using angularjs, which displays a list of items i'm following (docs, sites). I display the items as tiles (in rows of 4 below each other), and to fit the app part nicely on any page, I calculate the height of the most outer div (topContainer) which contains all items). I calculate the height when the ng-repeat finishes rendering (with a custom directive). The resizing is done with a postmessage:
var resizeAppPart = function (width, height) {
if (senderId && hostweburl) {
var message = "<Message senderId=" + senderId + " >"
+ "resize(" + width + "," + height + ")</Message>";
window.parent.postMessage(message, hostweburl);
}
}
The height and width are provided by
var heightDoc = $("#topContainer").height();
var widthDoc = $("#topContainer").width();
myUtils.resizeAppPart(widthDoc, heightDoc);
If I use
$(document).height/width();
it delivers the same result.
This works perfectly when loading the page.
However I also provide a button which allows a user to 'unfollow' any of the displayed items. Then the item disappears (splice from the array, the repeat gets updated nicely), and I try to recalculate the height of the app part (so no gap remains when unfollowing an item). I can successfully call the recalculate size function for the app part (that's not the problem) however I just can't get the right height of the app part.. The height remains the same as before unfollowing an item, even though there's now a gap where the unfollowed item was..
So I'm trying to find a method to get the right height of the app part after removing the item from the array. Any Ideas?

Related

Detecting which node is selected within a slate-react text editor

I am currently working on a slate text editor where the user can add images and text. I would also like to have a hovering toolbar which serves different buttons depending on what type of element the user has selected.
For example if the user has selected an image then I would like to serve one set of buttons. If the user has selected a paragraph I would like to serve another set of buttons.
After looking through the examples found here:
https://www.slatejs.org/examples/richtext
I have pieced together a rough example of my desired text editor without the context dependant hovering toolbar buttons:
https://codesandbox.io/s/suspicious-pine-lrxgw
But I am struggling to work out how to detect what type of element is selected within the editor? I don't know if there is a way to do this using slate-react? Or even in vanilla JS?
Ideally I would also be able to get other information about the element as well. For example the images height and width as this would help with styling.
Any help appreciated
You can get the currently focused node by using the selection property from the editor and which is a Range. You then use the anchor or focus to select the currently selected children.
anchor & focus are Points which are basically an array the first item is the current block and the second item indicates the position in the block.
Point objects refer to a specific location in a text node in a Slate
document. Its path refers to the location of the node in the tree, and
its offset refers to distance into the node's string of text. Points
may only refer to Text nodes.
using the selection array we can get the current selected block like so
if (selection !== null && selection.anchor !== null) {
selected = editor.children[selection.anchor.path[0]];
} else {
selected = null;
}
Later in your render function you can have a check to render what you want.
Here, path comes from selection.anchor.path, which I noticed will walk into leaves down to a final text node (I want the cell of my table, not the text), same with paragraphs. I want the full { type: 'paragraph', children: [...text node] }, not just the text. So, I pop the end off and reduce.
const pathClone = [...path];
pathClone.pop(); // get rid of trailing text node postion in path.
const focusedNode = pathClone.reduce((node, pathPosition) => {
if (!node) return editor.children[pathPosition];
return node.children[pathPosition];
}, null);
// console.log('last node type before text node: ', focusedNode.type, focusedNode);

Change text when image is displayed on scroll react

I'm building a portfolio website with React with large full width vertically scrolling images. There is a single text box on the side of the webpage that I would like to display the title of each image as each image comes into view.
Any recommendations on how to change the text in a DIV when an image comes into view? I'm not even sure what to search to find an answer to this. Any help is much appreciated. Thanks!
You can attach an onscroll listener to detect when the user scrolls. Inside the listener, you need to do some math to calculate which element is currently viewed. The variables you can use for the calculation are scrollTop (on the container, used to determine the current scroll position) and the clientHeight of each element.
let nameDisplayDiv = document.getElementById('display')
let containerDiv = document.getElementById('container')
function refresh() {
let scrollTop = containerDiv.scrollTop + containerDiv.clientHeight / 2
let height = 0
for (let child of containerDiv.children) {
let top = height
let bottom = height += child.clientHeight
if (top < scrollTop && bottom > scrollTop) {
// Found the element that's currently viewed!
nameDisplayDiv.innerHTML = child.style.backgroundColor
break
}
}
}
containerDiv.onscroll = refresh
Here's a working fiddle:
https://jsfiddle.net/uxh91Leq/2/

Delete one slide from a Google Slide Presentation using Google Apps Script

I need to use Google Apps Script, not the API.
I create an empty presentation
It seems newly created presentations always contains an empty slide by default
I insert a slide (taken from an other prez) into the presentation.
-> I'd like to delete this empty slide, so that the presentation contains only the slide I paste into it.
The code I have:
var presentation = SlidesApp.create("my new presentation"); // creates an empty slide in the prez
presentation.insertSlide(0,slides.pop()); // a slide from a deck of slides collected elsewhere
presentation.getSlides().pop(); // here trying to delete the empty slide, doesn't work: the slide remains in the presentation.
presentation.saveAndClose();
You need to remove the Slide. pop() just removes it from the array and returns the last slide in the Slide [].
var lastSlide=presentation.getSlides().pop();
lastSlide.remove();
To remove the first slide, use the shift() method. The shift() method pulls the first element off of the given array and returns it.
// Remove first blank slide
const removeFirstSlide = newPresentationSlide.getSlides().shift()
removeFirstSlide.remove()
But remember, to remove the first blank slide, you need more slides in your Presentation.

ngInfiniteScroll initially fill container-element with results

I have a scope with 150 elements in it and I'm using ngInfiniteScroll to alowe users to scroll through those results. But in my project I can't get the directive to initially fill the container element. It shows the number of results that I want to add whenever the bottom of the element has been reached, and because of that there's no scrollbar so users can't scroll to get to the extra content.
http://plnkr.co/edit/B7CRjvdQ9paytwl5csKi?p=preview
$scope.loadMore = function() {
for(var i=0;i<10;i++) {
if($scope.movies.length) {
var movie = $scope.movies.pop();
$scope.pagedData.push(movie);
}
}
}
If I change the 10 to 20 it starts with 20 examples. The desired result is that the container element is filled with results untill a vertical scrollbar shows up, from then it should only add results when the bottom of the element has been reached.
You can use infinite scrolling feature of ag-grid
AG-Grid

AngularJS : ui-grid: dynamic expandableRowHeight

ui-grid's expandable row feature works great if every parent row has the same number of subrows in its subGrid, and therefore the same height. Not so great if the number of subrows in the subGrid varies from row-to-row of the parent.
I've been able to get the subGrid ITSELF to have a dynamic height by passing in the array length and using that to generate a subGrid-height:
lengthOfList: data[i].friends.length
style="height:{{row.entity.subGridOptions.lengthOfList * 30}}px;
But since that subGrid has to live WITHIN the parent grid, the parent grid needs to push its rows down to make room. And it needs to do so by a different amonut for each row. Unfortunately the parent grid has a single, fixed expandableRowHeight for ALL rows. I can't specify the expandableRowHeight for EACH row.
Best I can hope for is to alter the expandableRowHeight on-the-fly, as I click on a row to open it.
Trying to figure out how to listen for the open expandable row event.
ui-grid is a shrink-wrapped plugin that writes it own DOM elements, so I have no way of adding anything to the elements that might help me capture events on them.
How can I configure the expandableRowHeight on-the-fly?
Plunker:
http://plnkr.co/edit/1IeEsXZAf9pRgKmy5jfO?p=preview
(The plunker is misbehaving. 1] A font that ui-grid is using is now blocked due to cross-domain issues, 2] sometimes the html template goes AWOL for no discernible reason.)
Ah. I found the gridApi. So this solution works!
$scope.gridOptions = {
onRegisterApi: function(gridApi) {
gridApi.expandable.on.rowExpandedStateChanged($scope,function(row){
$scope.gridOptions.expandableRowHeight = row.entity.mySubRowItems.length * 30;
});
}
}
I'm sure there's a way of referring to the row's parent grid directly. Instead of $scope.gridOptions, there's surely some row $parent reference, I just haven't found it yet.
As an update for 3.0.0 stable there is a rowExpandedBeforeStateChanged event. If you use rowExpandedStateChanged then your grid won't update w/ the new expandableRowHeight you're trying to set.
$scope.gridOptions.onRegisterApi = function(gridApi) {
// dynamic expandable rows
gridApi.expandable.on.rowExpandedBeforeStateChanged($scope, function(row) {
$scope.gridOptions.expandableRowHeight = 30 + row.entity.valueArray.length * 30;
});
};
Finally got this sorted, the important thing to know is that the expandable row has a row height, and a sub (expandable) grid size height inside that row, so if you need to display the grid to fit exactly inside the row, you need to set both heights to the same dynamic size.
Inside your top level grid api you need to specify :
$scope.gridOptions = {
onRegisterApi: function(gridApi) {
gridApi.expandable.on.rowExpandedStateChanged($scope, function (row) {
row.expandedRowHeight = (row.entity.subGridOptions.data.length * rowHeight) + headerHeight;
});
});
}
}
but now u use the expandedRowHeight variable from ui-grid version 3.0.0+, not available in 2+, the expandableRowHeight does not seem to have any affect, but might be used to set the global value for expandedRowHeight. (Note the different naming of these 2 variables on the grid)
Now this will size your top Grid row to display your sub grid correctly.
In the expandableRowTemplate.html for the sub grid u need to specify the height dynamically of the sub grid using the css style:
<div ui-grid="row.entity.subGridOptions" style="height:{{(row.entity.subGridOptions.data.length * rowHeight) + headerHeight}}px" ui-grid-auto-resize></div>
this works very well for me currently, and might help someone out there.
Note that it could also help to investigate the ui-grid-autoresize directive now in ui-grid 3+, apparently this helps in accomplishing this, not 100% sure if I used it correctly, but it works
This is how it works, I checked other people's solution, they all not working
Let's assume that the headerRowHeight is 39px.
The template should be something like this :
'<div ui-grid="row.entity.subGridOptions" ng-style="{height: (row.entity.youList.length * row.entity.subGridOptions.rowHeight) + 39 + \'px\'}" ui-grid-selection ui-grid-edit ui-grid-cellnav ui-grid-validate ui-grid-auto-resize ui-grid-resize-columns></div>'
The rowExpandedStateChanged should be this:
gridApi.expandable.on.rowExpandedStateChanged($scope, function (row) {
$timeout(function() {
row.expandedRowHeight = row.entity.youList.length * row.entity.subGridOptions.rowHeight + 39;
}, 150);
});
I tried a different approach to the solution using CSS alone instead of leveraging the "expandableRowHeight" property. And this worked for me.
The parent grid data is rendered inside a div with class name "ui-grid-canvas". Add the following style -
.ui-grid-canvas{
height: auto !important;
overflow: auto !important;
}
For expanded child table, add a style to div with class name "expandableRow"
.expandableRow{
height: auto !important;
}
Also, do not set the "expandableRowHeight" property in gridOptions.

Resources