I am trying to get the height of an element which will appear when mouse over of a button.
Example code:
<div ng-mouseenter="mouseoverPopUp()" ng-mouseleave="showpop=false">menu</div>
<div class="popover" ng-show="showpop">{{content}}</div>
$scope.mouseoverPopUp = function($event){
$scope.showpop = true;
var height = angular.element(".popover").innerHeight();
};
The problem is sometimes the height of the element is being get before it is appeared. Is there anyway I can run the code only have the ng-show has show the element? I need to get the height ASAP after it appear to adjust the position of the element.
Have you tried with your code inside a $timeout call in order to delay the execution of your JS after angular finished working ?
$scope.mouseover = function($event){
$timeout(function() {
var height = angular.element(".popover").innerHeight();
});
};
How are you showing your popover? with a css transition ? If so you'll need to delay accordingly your JS code retrieving the height. Or you can use angular-animate to bind events with more logic
ps: to help more, a jsfiddle would be great
Related
I'm attempting to use the solution here to scroll a container to a certain position. Here's my version:
var wrapper = angular.element(document.getElementById('myWrapper'))[0];
var container = wrapper.querySelector('#myContainer');
var anchor = wrapper.querySelector('#myAnchorWithinTheContainer');
scrollContainerToAnchor(container, anchor);
...
function scrollContainerToAnchor(container, anchor) {
var element = angular.element(anchor);
angular.element(container).animate({scrollTop: element.offset().top}, "slow");
}
However, angular.element returns an array, so I don't see how that answer can work... but even if I correct it to the following:
function scrollContainerToAnchor(container, anchor) {
var element = angular.element(anchor);
angular.element(container)[0].animate({scrollTop: element[0].offset().top}, "slow");
}
the browser will still complain that "element[0].offset is not a function". So, I attempted to use getBoundingClientRect() instead:
function scrollContainerToAnchor(container, anchor) {
var element = angular.element(anchor);
angular.element(container)[0].animate({scrollTop: element[0].getBoundingClientRect().top}, "slow");
}
but then the browser gives me "Failed to execute 'animate' on 'Element': The provided double value is non-finite" (in my case, the "non-finite" value that it's complaining about is 3282.9375(?)).
Anyway, the fact that the above-linked answer has (as of today) 10 upvotes and no complaints in the comments suggests that I am missing something, not that the answer is incorrect... So, what am I missing?
If there's a better way to scroll a div without using jQuery and without scrolling the whole page in addition to the div (I've already looked at $anchorScroll, but it scrolls both the window and the div), I'm up for other suggestions/techniques.
The answer referenced above requires jQuery. The offset function is part of jQuery. Angular makes use of jQuery Lite aka jqLite, which has no offset function.
To scroll the div without jQuery, I did the following:
HTML:
...
<div id="myScrollableDiv">
...
<div id="elementIWantToScrollTo">...</div>
</div>
<div in-view="scrollableDivIsVisible()"></div>
...
Controller:
angular.module('myModule')
.controller('MyCtrl', ['$scope', function($scope) {
...
var _hasBeenScrolled = false;
$scope.scrollableDivIsVisible() {
if (!_hasBeenScrolled) {
document.getElementById('elementIWantToScrollTo').scrollIntoView();
_hasBeenScrolled = true;
}
}
}]);
Note that scrollIntoView() causes both the window and the div to scroll (similar to $anchorScroll, but easier to use and doesn't add a hash tag to the URL). Since one of the requirements is to NOT scroll the window, I avoid that by using the in-view directive to detect when the bottom of my scrollable div is visible. Thus I only trigger scrollIntoView() when scrolling the window won't matter/is already complete. Then I use _hasBeenScrolled to ensure scrollIntoView() doesn't interfere with any scrolling that the user did (i.e. it's only auto scrolled once).
If you need to scroll a div based on some other trigger, rather than when the user first sees it, as was my need, then you can use the in-view directive to set a variable and then $scope.$watch() that variable before running your other trigger.
Maybe there's a better "Angular way" to do it, but the above gets the job done, and doesn't need jQuery.
I have created a script that adds the scrollTop value to the height of a DIV
var scroll = $(this).scrollTop();
console.log(scroll);
function scrollH() {
document.getElementById("overlay").style.height = scroll + 'px';
}
document.getElementById("overlay").addEventListener("scroll", scrollH());
I need this style to keep updating (I'm making a progress bar). Currently it only changes when I refresh the page.
Thanks in advance
(Sorry if I did not follow the correct question format for this site, this is my first question :L )
You want to apply styles via JavaScript after the DOM has loaded.
JQuery helps with this:
$(document).ready(function() {
//do something to css
});
https://learn.jquery.com/using-jquery-core/document-ready/
You could apply a listener to whatever event is triggering an update, and then replace or fill the progressbar with it's new value.
I have been googling for a while and so far I found how to resize window with window resize directive but in my code I'm using window.innerHeight to get initial height. I can use it any time except I need an event to when it changes. JavaScript window resize event does not fire for me for some reason. Here is my code inside of the controller:
function adjustH() {
var bodyElem = document.getElementsByTagName('body')[0];
var topP = window.getComputedStyle(bodyElem, null).getPropertyValue('padding-top');
topP = topP.substring(0, topP.indexOf("px"));
var bottomP = window.getComputedStyle(bodyElem, null).getPropertyValue('padding-bottom');
bottomP = bottomP.substring(0, bottomP.indexOf("px"));
vm.h = window.innerHeight - topP - bottomP - 20;
}
window.onresize = function(event) {
adjustH();
}
Can anybody tell me if it is impossible to do it this way and I have to go the directive route? Or if its possible please tell me what I'm missing.
If you are working with angularJS, did you pass $window as a dependency to you controller.
I have had similar issues with this before and it was because the depoendency was not set.
Hope this helps.
After reading your comment which stated
Also my canvas set to height="{{vm.h}}" but it only resizes when I mouse over
It seems that you need to call $scope.$apply() (or $rootScope.$apply()) in order to update the height property of the element.
If you add more code from your directive/controller, I could give you a more detailed answer.
I have a scroll-view has one fa-surface that contains the html for my page. The height for this `fa-surface' is dynamic since it can be larger or smaller depending on the width of the page.
I have set the fa-modifier size to fa-size=[undefined, true] (Read that true sets the height to the surfaces height).
This results in a page that will not scroll. If I put a fixed height in the fa-size it will work, but that does me no good as the page is responsive and the height is dynamic.
Here is the code for the page:
<fa-app style="height:100%">
<fa-scroll-view fa-pipe-from="eventHandler">
<fa-view>
<fa-modifier fa-size="[undefined, true]">
<fa-surface fa-pipe-to="eventHandler">
Misc HTML...
</fa-surface>
</fa-modifier>
</fa-view>
</fa-scroll-view>
</fa-app>
Here is the simple controller for piping the events.
angular.module('newvitalwallApp')
.controller('MainCtrl', function ($scope, $famous) {
var EventHandler = $famous['famous/core/EventHandler'];
$scope.eventHandler = new EventHandler();
});
The live page is on a dev server here if your curious how it is behaving :
http://staging-sqtmp3dxdz.elasticbeanstalk.com/
I am at a loss as to why this is not working.. I am new to famous, but I have scoured the internet for answers on this and have found very little.
Thanks in advance for your input.
I just created a service that will handle true for width and height temporarily, but also logged the issue in the f/a issue tracker so hopefully the team will fix.
var faTrueService = function($famous){
this.height = function(cl){
if($famous.find(cl)[0].renderNode._currentTarget !== null && $famous.find(cl)[0].renderNode._currentTarget.children[0] !== undefined){
return $famous.find(cl)[0].renderNode._currentTarget.children[0].clientHeight;
}
};
this.width = function(cl){
if($famous.find(cl)[0].renderNode._currentTarget !== null && $famous.find(cl)[0].renderNode._currentTarget.children[0] !== undefined){
return $famous.find(cl)[0].renderNode._currentTarget.children[0].clientWidth;
}
};
};
In the template, you can now do the following:
<fa-modifier fa-size="[undefined, faTrue.height('.item-1')]">
<fa-view fa-index="1">
<fa-surface class="item-1" fa-pipe-to="pageScrollHandler">
When Surfaces get deployed, a resize event gets attached to the them that forces the Surface to reevaluate it's size, so the Service will get called on resize automatically.
Since you can't just use Services in a template, I created a helper function that calls the Service on the current Controller or Directive scope I'm working with.
//temp fix for true
$scope.faTrue = {
height : function(cl){
return faTrue.height(cl);
},
width : function(cl){
return faTrue.width(cl);
}
};
The child .fa-surface being targeted might have to get the following styling for this to work:
.fa-surface{
overflow:hidden;
height:auto;
width:auto;
}
I don't understand why the previous answer uses the callback for sync, this doesn't make sense, especially since the size is getting reevaluated on resize of Surfaces, not on an event attached to the scrollview.
Since all the children of the Scrollview now have height, it will automatically adjust it's height as well in Famo.us 0.3.0
So, though I do feel setting the size of the fa-modifier to [undefined,true] should be enough to set the height of the scrolled content, it's not enough.
So I added function that checks the height of the content on scroll and updates the fa-size dynamically. Here's the code I added the original controller:
$scope.$on('$viewContentLoaded', function(){
$famous.find('fa-scroll-view')[0].renderNode.sync.on('start', function(event) {
var test = angular.element( document.querySelector( '#test' ) );
$scope.testHeight = test[0].clientHeight;
});
});
$scope.getTestHeight = function() {
return $scope.testHeight;
}
Then I changed the fa-size in the view to [undefined, getTestHeight()]
There very well may be a better way of doing this, and ultimately I think it should be handled automatically by famous-angular, but for now this solves it.
I have a modal dialog (window.showModalDialog) with html in it. when I resize the dialog, the HTML within it does not repect the new boundaries and I get scroll bars or elements that don't expand 100% to the new width.
To fix this I have to drag it around for a bit and it then jolts it self back into the correct sizes.
To fix it programtically. I do the following window.document.getElementById('removeMainBody').innerHTML =window.document.getElementById('removeMainBody').innerHTML;
But this causes some dynamic objects in the html to stop functionin.
How can i solve this problem and make the elemnts within the dialog resize after I resize the dialog?
Here is my code
else if(<c:out value="${staffCount}" /> > 1){
document.getElementById('removeDiv').style.display = '';
window.dialogWidth='770px';
window.dialogHeight='320px';
window.document.getElementById('removeMainBody').innerHTML =window.document.getElementById('removeMainBody').innerHTML;
}
If you set a style or a Class from the Body-Tag, this should force an HTML Reflow, and the Site would be displayed correct again, without setting the innerHTML Property.
example:
...
window.document.body.className = "relfow";
// if the body class Attribute was set, than set it now back
window.document.body.className = "oldBodyStyleClassName" ; / Or just to ""
...
if the browser optimizes, the refresh calls, so that now reflow occures you could
setTimeout(function(){
...
window.document.body.className = "relfow";
// if the body class Attribute was set, than set it now back
window.document.body.className = "oldBodyStyleClassName" ; / Or just to ""
...
})
i hope this helps. (here you can find some info to Reflow Link)