Resizing divs on window resize using AngularJS - javascript

I'm trying to use a directive to resize a few divs on my page (5 to be exact). They're all columns which I'd like to resize so they always stretch to the bottom of the window.
I used this as a guide: Window resize directive
Coming up with this:
app.directive('resize', ['$window', function($window) {
return {
link: function(scope, elem, attrs) {
scope.onResize = function() {
var padding = 30,
offset = elem.prop('offsetTop'),
height = $window.innerHeight - offset - padding;
elem.css({height: height + 'px'});
}
scope.onResize();
angular.element($window).bind('resize', function() {
scope.onResize();
})
}
}
}]);
I've given my divs the directive element identifier of "resize".
On load, it works great - all divs are correctly sized. But, on changing window size, only the last rendered div is resized. I'm guessing it's because the resize window event is being overwritten each time with the scope of each div in turn, and so by the time the page is loaded, the window resize event only refers to the last rendered div.
How would I go about it so the resize event applies to all divs and not just the last one?

While looking into a completely unrelated issue, I realised I just needed to set the scope:
app.directive('resize', ['$window', function($window) {
return {
scope: {},
link: function(scope, elem, attrs) {
....
}
}
}]);

Related

Infinite scroll detecting bottom of page only if there is nothing underneath

I'm doing an infinite scroll page with angularjs that loads more items when the user reaches the bottom of the page. My problem is that under the infinite scroll container may or may not have more "stuff". So i don't want to load more items if the user reaches the bottom of the page if that "stuff" is present. So i want to load more items when the infinite scroll container reaches the end of that container and not the end of the page.
For the infinite scroll i have an angularjs directive like this:
myApp.directive("scroll", function ($window) {
return function(scope, element, attrs) {
angular.element($window).bind("scroll", function(event) {
var docHeight = $(document).height();
var reachBottom = $($window).scrollTop() == (docHeight - $($window).height());
if (reachBottom) {
setTimeout(scope.loadMore(), 100);
}
});
};
});
you can get stuff height under infiniti scroll container and use it
var docHeight = $(document).height();
var stuffHeight = $('#stuff').height();
var reachBottom = $($window).scrollTop() == (docHeight - ($($window).height() + stuffHeight));
if (reachBottom) {
setTimeout(scope.loadMore(), 100);
}
Only using jQuery you can do it. See this code snippet below.
<script>
$(function () {
var w = $(window);
loadNewPage();
// Each time the user scrolls
w.scroll(function () {
// End of the document reached?
if ($(document).height() - win.height() == win.scrollTop()){
loadNewPage();
}
});
});
</script>

Angular.js Client height

I have an angular.j app, which has a view and a directive. The various views used have different client height. I am trying to place a default background on the view, while various views have different page heights.
To place a background on the screen, I need to know the client window height, which is the minimum height that the background will be set to. The height of the view, if this is bigger than the client height, the background would need expanding to cover the extra height.
The view:
index.html
<body ng-app="myApp">
<div main-container></div>
<script src=......></script>
</body>
The view controller
js/app.js
var myApp = angular.module('myApp', ['ngRoute']);
myApp
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/home.html'
})
.otherwise({redirectTo: '/'
});
}]);
The Home view
views/home.html
<div style="height: 2000px">
<p>Home View content</p>
</div>
The view directive for main-container
js/directives/main.js
myApp.directive('mainContainer', ['$window', function($window) {
return {
link: function(scope, elem, attrs) {
scope.onResize = function() {
var header = document.getElementsByClassName('main-container')[0];
elem.windowHeight = $window.innerHeight - header.clientHeight - 80;
$(elem).height(elem.windowHeight);
}
scope.onResize();
angular.element($window).bind('resize', function() {
scope.onResize();
})
}}
}])
The view directive does not get the height of the view, it gets the client window height when ever the page is re-sized & refreshed. I would like to also get the view height, so that I can set the height of the container background to either the client height or view height, which ever is the bigger.
I'd like to do is get the height of the view, as set in the home.html css, is there a way to do this?
Please assist.
I'd suggest you to put you directive attribute on ng-view element, also your directive needs some changes. In order call calculation function for height scope.onResize you need to call it on element.on('load') also will ensure that the every time view changes will call scope.onResize function.
Directive
myApp.directive('mainContainer', ['$window', function($window) {
return {
link: function(scope, elem, attrs) {
scope.onResize = function() {
var header = document.getElementsByClassName('main-container')[0];
elem.windowHeight = $window.innerHeight - header.clientHeight - 80;
$(elem).height(elem.windowHeight);
}
scope.onResize();
angular.element($window).bind('resize', scope.onResize);
//below function will call on view change in ng-view
element.on('load', function(){
$scope.$apply(scope.onResize);
})
}}
}])

How to get elements height of an element dynamically loaded inside an ionicdialog

I have a modal dialog based on a template in which i load a GoogleMap.
I want the GoogleMap to take the remaining Space below a header and a sub-header included in the template.
-- header -- (height is defined through mediaqueries in css)
-- subheader -- (height is defined through mediaqueries in css)
-- remaining space inside dialog --
This is my controller so far:
$scope.creategooglemapsmodal = function() {
$scope.item.showmap = true;
$ionicModal.fromTemplateUrl('templates/Gmapdialog.html', {
scope: $scope,
animation: 'slide-in-up'
})
.then(function (modal) {
$scope.googlemapsmodal = modal;
$scope.googlemapsmodal.show()
.then(function() {
// after showing the modal i would like to adjust the mapcontainers height - before i initiate the map, which will call the containers height.
$scope.showmapinit();
$scope.modalhiddenlistener = $scope.$on('modal.hidden', function() {
$scope.hidegooglemapsmodal();
});
});
});
};
What is the recommended way to handle this?
I've found a solution:
after initialization of the GoogleMap i call
map.fitBounds(bounds);
to set Zoom and Center (after placing markers)
And right after that i call:
$scope.googlemapsmodal.$el.find('.angular-google-map-container').addClass('expander');
The CSS looks like this:
.expander {
position:inherit !important;
-webkit-transform: none !important;
}
Hope this will help someone

Accessing the element a directive is bound to

I want to create a directive that is applied to elements to set their max height equal to the window height minus the distance from the top of the element to the top of the window.
I was trying it like this
.directive('resize', function ($window) {
return function (scope, element) {
var w = angular.element($window);
scope.getWindowDimensions = function() {
return { 'h': w.height() };
};
scope.$watch(scope.getWindowDimensions, function(newValue, oldValue) {
//get header height including margins
var headerHeight = $('.page-header').outerHeight(true);
scope.windowHeight = newValue.h;
scope.style = function() {
return {
'height': (scope.windowHeight - headerHeight) + 'px',
'max-height': (scope.windowHeight - headerHeight) + 'px'
};
};
}, true);
w.bind('resize', function() {
scope.$apply();
});
}
})
But I would have to add a var for every element that is above the element whose height I want to set. So I believe using
var scrollTop = $(window).scrollTop(),
elementOffset = $('#my-element').offset().top,
distance = (elementOffset - scrollTop);
would be better as it does all the measurements relative to the element its setting but how do I access this element from within the directive without adding any extra classes or identifiers?
Also do I need to create an isolate scope for me to use this more than once on a single page?
My goal is to basically have my web apps body element equal to the height of the window and any containing divs that are higher than that height to have scroll bars.
1)It would be better if you have isolate scope. so that the directive can be user multiple elements with different heights.
2) Send an array of elements (Which are above the required element) as an attribute to the directive. And calculate the height to be deducted from window height.

How can I trigger resize event in AngularJS

I'm using Angular & Bootstrap, with the nav tab control to switch visibility of divs. In one div, I have a large img (CAD drawing of building). I also then overlay markers on the image. I want to scale the x/y position of the markers based on the image width & image naturalWidth. I'm using a resize directive to detect changes and update my scope.
My problem is that if user switches tabs and switches back to the div with the CAD img, the refresh doesn't happen until I resize the browser (or surprisingly if I press the CMD key on Mac).
Is there an angular way to trigger the resize event to force my markers to be recalculated. Or is there an event I can tap into that is fired when the is fully displayed ?
Or is there a more refined angular approach I should take?
This is the HTML, the resize directive I've written is on the tag.
<div id="imageDiv" style="position: relative;" ng-show="selectedLocation" >
<img ng-src="../maps/image/{{selectedLocation}}"
style=" max-width: 100%; max-height: auto; border:solid 1px black" resize imageonload />
</div>
And this is the resize directive (adapted from http://jsfiddle.net/jaredwilli/SfJ8c/)
directive('resize', function($window) {
return function(scope, element) {
var w = angular.element($window);
scope.imgCadImage = element;
scope.getWindowDimensions = function() {
return {
'h' : scope.imgCadImage[0].width,
'w' : scope.imgCadImage[0].height
};
};
scope.$watch(scope.getWindowDimensions, function(newValue, oldValue) {
if (scope.imgCadImage[0].naturalWidth)
scope.imgScale = newValue.w / scope.imgCadImage[0].naturalWidth;
else
scope.imgScale = 1;
console.log("watched resize event - scale = "+scope.imgScale)
scope.updateCADMarkersAfterResize();
}, true);
w.bind('resize', function() {
console.log("'resize' - scale = "+scope.imgScale)
scope.$apply();
});
};
}).
This worked for me when the above did not.
$timeout(function() {
$window.dispatchEvent(new Event("resize"));
}, 100);
I had to also use $timeout with a delay in my case to prevent errors about digest cycles already being in progress. Not all uses cases may need this.
dispatchEvent is well supported http://caniuse.com/#feat=dispatchevent
However, it you need IE9 and IE10 support you'll have to use their propritary method: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/fireEvent
Try injecting $timeout into the resize directive:
directive('resize', function($window, $timeout) {
... then add the following line to the bottom of it:
$timeout(function(){ w.triggerHandler('resize') });
This should trigger the handler you have bound to $window.resize just after the browser renders.
The accepted answer did not work for me - w is undefined.
This did:
$timeout(function(){
$(window).trigger('resize');
});

Categories