I am new to AngularJS, and since I have been pursuing a solution to the problem for several days (perhaps a week), it indicates to me that I am not using it correctly.
The problem: the need to position 30 divs in the following way:
1) each of which displays a number indicating one of the 30 days of a month, in sequential, increasing order from '01' to '30' (so a strict integer won't work for display)
2) positioning on the right side of the viewport, at all times, with any device/orientation (limited to screen height > 525 px and phones in portrait orientation
3) and in such a way that the maincontroller 'knows' the exact pixel distance from the top after page load and every resize
4) such that each div is uniquely identified with an index number corresponding to a 0-based array numbering scheme
And now for some serious convolution:
1) I am loading a json file of this format using $http
[
{
"dayDisplay" : "01", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "02", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "03", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "04", "isPayDay" : false, "positionX" : "0"
},
...
and ng-repeating through it with a 'partial' view:
<div id="days-list-control" ng-controller="DayListController">
<div x-day-index="{{$index}}" day-position-update distribute-days-vertically class="day-div" ng-repeat="item in allDayData">
<span ng-class="{'pay-day':(item.isPayDay === true), 'pay-day-hidden':(item.isPayDay === false || $index === state._currentDayIndex)}">$</span>
<span ng-class="{'hide-day':($index === state._currentDayIndex), 'day':($index > state._currentDayIndex), 'past-day':($index < state._currentDayIndex)}">{{item.dayDisplay}}</span>
</div>
</div>
And using these 2 directives to massage the DOM and position these divs the way I want to:
layoutManagerDirectives.directive('dayPositionUpdate', ['$window', '$parse', function($window, $parse) {
return {
priority: 1,
link : function(scope, element, attrs) {
angular.element($window).bind('load', function() {
var position = $parse(element[0].attributes['x-daydivtop'].nodeValue)(scope);
var elementId = $parse(element[0].attributes['x-day-index'].nodeValue)(scope);
scope.$apply("updateDayPositions('" + position + "','" + elementId + "')");
});
angular.element($window).bind('resize', function() {
var position = $parse(element[0].attributes['x-daydivtop'].nodeValue)(scope);
var elementId = $parse(element[0].attributes['x-day-index'].nodeValue)(scope);
scope.$apply("updateDayPositions('" + position + "','" + elementId + "')");
});
}
};
}]);
layoutManagerDirectives.directive('distributeDaysVertically', ['$window', function($window) {
return {
priority: 0,
link : function(scope, element, attr) {
angular.element($window).bind('resize', function(e) {
var containerElement = angular.element(document.getElementById('days-list-container'));
var dayDivTop = element[0].offsetTop;
if ($window.innerHeight < 645) {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
} else {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
}
});
angular.element(window).bind('load', function() {
var containerElement = angular.element(document.getElementById('days-list-container'));
var dayDivTop = element[0].offsetTop;
if ($window.innerHeight < 645) {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
} else {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
}
});
}
}
}]);
and the function in MainController invoked in the directive above is:
$scope.updateDayPositions = function(p, id) {
$scope.allDayData[id].positionX = p;
}
which simply updates the json-inspired object ("allDayData" which lives in the MainController) with the positioning info from the DOM attributes of all the divs ng-repeated thru (see the partial view: "ng-repeat='item in allDayData'"). This is so I can position yet another graphic element very precisely over each of the day numbers, programmatically, based on user input.
This works perfectly after I re-size the browser window. On load, I believe that the DOM elements aren't on screen and in a knowable position, since the allDayData object is not updated from its original positionX values of '0'. I am getting sporadic and odd behaviors after refreshing the page but most commonly, I see that the positionX data is not updated until I resize the browser window, after which point it works quite well. I have tried the following ways to invoke the directive:
1)
angular.element(window).bind('load', function() {
...
});
2)
angular.element(document).ready(function() {
...
});
3)
$timeout
4)
putting the code into a controller which in theory executes when loaded
Phew. I may have left something out, but hopefully there's enough here to say generally which direction I should go in if indeed a different one is optimal. Apologies for the astonishingly long question, and thanks in advance for any guidance.