Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS, D3 and JQuery in the same page. D3 can't read the correct DOM dimensions

I am struggling with my page that can't load properly. I am using a simple header-body-footer structure in html5 and CSS3.

    +----------+
    |  HEADER  |
+---+----------+---+
|       BODY       |
+---+----------+---+
    |  FOOTER  |
    +----------+

What I am doing right now is create a svg with D3 inside the body space, reading width and height dynamically after window is loaded (and pictures also).

Now I want to add angular to avoid code redundancy inside each page of the site and I did this:

(function() {
    var app = angular.module('neo4art', []);

    var pages = {
            "genesis.html": "The genesis of the project",
            "about.html": "About Us",
            "team.html": "The Team",
            "index.html": "Traversing Art Through Its Connections"
    }

    app.directive("header", function() {
        return {
            restrict : 'E',
            templateUrl : 'header.html'
        };
    });
    app.directive("footer", function() {
        return {
            restrict : 'E',
            templateUrl : 'footer.html'
        };
    });

    app.controller('menuController', function($scope, $location, rememberService){
        $scope.isActive = function(route){
            return rememberService.getActualPage() === route;
        };
    });
    app.controller('MainController', function(Page){
        this.page = pages;
    });

    app.factory('rememberService', function($location) {
        return {
            getActualPage: function(){
                var arr = $location.$$absUrl.split("/");
                var pageName = arr[arr.length -1];
                return pageName;
            }
        };
    });
    app.factory('Page', function(rememberService) {
        return {
            getTitle: function(){
                return "neo4Art - "+ pages[rememberService.getActualPage()];
            }
        };
    });

})();

To handle footer and header with Directives (< header>< /header>)

this is (part of) the code used to create the svg. I will only show you what I am interested in, the part that read the "on-field" measurements.

function Search(){
    var width = $(".container-svg").width();
    var height = $(".container-svg").height();
    console.log("width:" + width + " - height:"+ height);   
}

Before the use of angular I was using this in:

$(window).load(function(d) {
    var search = new Search();
});

and all was going pretty well.

now using:

angular.element(window).load(function() {
    var search = new Search();
});

I have a wrong height inside the var. It seems like the "new Search()" is called when the svg is still too high (the header is not yet rendered)

This is the html of the index (simplified)

<!DOCTYPE html>
<html lang="it-IT" ng-app="neo4art" ng-controller="MainController as mc">
<head>
<meta charset="utf-8">
<script src="resources/js/jquery/jquery-2.1.3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" type="text/css" media="screen" href="resources/css/style.css" />
<link rel="stylesheet" type="text/css" media="screen" href="resources/css/style-index-new.css" />
<link rel="stylesheet" type="text/css" href="resources/css/font-awesome-4.3.0/css/font-awesome.min.css" />
<title>{{"neo4Art - " + mc.page["about.html"]}}</title>
</head>
<body>
    <script type="text/javascript" src="resources/js/angular.min.js"></script>
    <script type="text/javascript" src="resources/js/search.js"></script>
    <script type="text/javascript" src="resources/js/neo4art.js"></script>
    <div class="container-page scrollbar-macosx" when-ready="isReady()">
        <div class="content-home">
            <header></header>
            <div class="text-home">
                <svg class="container-svg">
            </svg>
            </div>
            <div class="footer">
                &copy; 2015 neo4<span class="palette-dark-blue">A</span><span class="palette-blue">r</span><span class="palette-orange">t</span> - All
                rights reserved &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="//www.iubenda.com/privacy-policy/430975" class="iubenda-white iubenda-embed"
                    title="Privacy Policy">Privacy Policy</a>
                </div>
        </div>
    </div>
</body>
</html>

This is the code of the header:

<div class="header">
                <div class="logo">
                    <a href="index.html"><img src="resources/img/neo4art-logo-big.png" /></a>
                    <div class="motto">Traversing Art through its connections</div>
                </div>
                <form method="get" action="graph.html" name="query">
                    <div class="menu">
                        <div class="search-bar-container">
                            <span class="icon"><i class="fa fa-search"></i></span><input type="search" id="search" placeholder="Search..." name="query" />
                        </div>
                        <ul>
                            <li><a href="javascript:void(0)" class="current">HOME</a></li>
                            <li><a href="about.html">ABOUT</a></li>
                            <li><a href="genesis.html">GENESIS</a></li>
                            <li><a href="team.html">TEAM</a></li>
                        </ul>
                    </div>
                </form>
            </div>

Without angularjs it is rendered correct, with angular I have a wrong value like the image is not loaded at all.

I hope my question is clear enough, the problem I think is in when each function is called during the load of the page.

EDIT: It's strange also that sometimes the page is loaded correctly (random occurency)

AngularJS version 1.3.16

like image 473
Gianmarco Avatar asked Jul 17 '15 14:07

Gianmarco


1 Answers

So you are having this weird cross road in understanding of angular. First lets talk about angular.element is not the same as a jquery element. You shouldn't be doing DOM manipulation from an element you create like that you should have a directive with a link function to make sure this is happening in the digest cycle when you want it to. This is a hard concept to get but I think the best example I can find is from this other question.

Angular.js: set element height on page load

This does a reasonable job of showing and explaining what we are talking about.

like image 53
James Avatar answered Oct 29 '22 19:10

James