My goal is to create a $watch function within a directive that monitors changes in the height and width of an element. This will allow the element to be centered on top of an image using the height and width values.
Below is my app.js code:
app.directive('centerElement', function ($timeout) {
return function (scope, element, attrs) {
scope.$watch(function () {
return {
'h': element[0].offsetHeight,
'w': element[0].offsetWidth
};
},
function (newValue, oldValue) {
var elementHeight = newValue.h;
var elementWidth = newValue.w;
/*To account for rounding errors and not loop*/
if(elementHeight % 2 === 0)
{
element.css('margin-top', '-' + ((elementHeight) / 2) + 'px');
}
else
{
element.css('margin-top', '-' + ((elementHeight + 1) / 2) + 'px');
}
if(elementWidth % 2 === 0)
{
element.css('margin-left', '-' + ((elementWidth) / 2) + 'px');
}
else
{
element.css('margin-left', '-' + ((elementWidth + 1) / 2) + 'px');
}
}, true);
element.bind('centerElement', function () {
scope.$apply();
});
};
});
Here is my html code:
<div class="row relativePosition">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 noPadding">
<img id="getStartedGiveGiftImage" ng-src="{{homeCtrl.getHomeImageBySectionName('getStartedGiveGift').url}}"/>
</div>
<div id="getStartedGiveGiftCol" class="absolutePosition" center-element>
<div class="col-lg-8 col-md-8 col-sm-8 col-xs-12">
<div class="getStartedGiveGiftText headingTitle">
Swapping, Sharing,
<div class="getStartedGiveGiftText text-right">
and Caring
</div>
</div>
</div>
<div id="getStartedGiveGiftButtons" class="col-lg-4 col-md-4 col-sm-4 col-xs-12 text-right">
<div>
<a id="getStartedGiveGiftButton1" class="btn btn-default text-right redBackgroundGradient" href="{{homeCtrl.getPage('Get Started').route}}">Get Started</a>
</div>
<div>
<a id="getStartedGiveGiftButton2" class="btn btn-default getStartedGiveGiftButton greenBackgroundGradient text-right text-white" href="{{homeCtrl.getPage('Give a Gift').route}}">Give a Gift</a>
</div>
</div>
</div>
</div>
I have already set the CSS for the .getStartedGiveGiftCol to:
#getStartedGiveGiftCol {
top: 50%;
left: 50%; }
By applying margin-top
and margin-left
values that are half the height and half the width, the element will be perfectly centered over the image.
During testing in Google Chrome, I noticed that the centerElement directive did not trigger when the image loaded and the element's dimensions changed, unless I stepped through the code in Developer Tools. No errors occurred when running the app without Developer Tools open. Similar behavior was observed in Internet Explorer and Firefox, but Edge successfully centered the elements.
Although I am hesitant to use $watch due to potential performance issues, I have not found an alternative solution in the AngularJS documentation or online searches. I have also tried waiting for the image to load before centering the element, but no luck so far. Since this directive will be used in other parts of the app, I am eager to explore alternative methods to achieve this without using $watch.
As a newcomer to AngularJS, any assistance is greatly appreciated. If more information is needed, please let me know.
Thank you!
EDIT: To address the issue, I created another directive for the image that triggers scope.$digest() upon loading. While this improved the situation, I still encountered occasional failures after refreshing the page multiple times. Any suggestions?
Below is the directive I implemented:
app.directive('imageOnload', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('load', function() {
scope.$digest();
});
element.bind('error', function(){
alert('image could not be loaded');
});
}
};
});