Q:

Cytoscape.js - layout() doesn't work in Firefox, works in Chrome

I have a page showing a graph with Cytoscape.js, but .layout() does not work for me in Firefox, however it does in Chrome.
Chrome shows the graph with the layout. Firefox shows the graph but all nodes are cluttered together. It looks the same in Chrome if I use no layout, so it seems the layout does not work in Firefox for some reason. 
I tried a few layouts from the Cytoscape.js website (http://js.cytoscape.org/#layouts) and they work in Chrome, but not in Firefox. I currently use the cose layout (http://js.cytoscape.org/#layouts/cose).
Firefox version is 52.0.2
Chrome is Version 57.0.2987.133
Cytoscape.js is version 3.0.0
My Javascript:
$( document ).ready(function() {
    $("#cy").attr("foo", "foo");
    var cy = cytoscape({
          container: $("#cy"),
          layout: {
            name: 'preset'
          },
          style: [
            {
              selector: 'node',
              style: {
                'content': 'data(id)'
              }
            },
            {
                selector: "edge",
                style: {
                    "line-color": "data(color)"
                }
            },
            {
              selector: ':parent',
              style: {
                'background-opacity': 0.6
              }
            }
          ]
        });
    var options = {
              name: 'cose',

              // Called on `layoutready`
              ready: function(){},

              // Called on `layoutstop`
              stop: function(){},

              // Whether to animate while running the layout
              animate: true,

              // The layout animates only after this many milliseconds
              // (prevents flashing on fast runs)
              animationThreshold: 250,

              // Number of iterations between consecutive screen positions update
              // (0 -> only updated on the end)
              refresh: 20,

              // Whether to fit the network view after when done
              fit: true,

              // Padding on fit
              padding: 30,

              // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
              boundingBox: undefined,

              // Randomize the initial positions of the nodes (true) or use existing positions (false)
              randomize: false,

              // Extra spacing between components in non-compound graphs
              componentSpacing: 100,

              // Node repulsion (non overlapping) multiplier
              nodeRepulsion: function( node ){ return 400000; },

              // Node repulsion (overlapping) multiplier
              nodeOverlap: 10,

              // Ideal edge (non nested) length
              idealEdgeLength: function( edge ){ return 10; },

              // Divisor to compute edge forces
              edgeElasticity: function( edge ){ return 100; },

              // Nesting factor (multiplier) to compute ideal edge length for nested edges
              nestingFactor: 5,

              // Gravity force (constant)
              gravity: 80,

              // Maximum number of iterations to perform
              numIter: 1000,

              // Initial temperature (maximum node displacement)
              initialTemp: 200,

              // Cooling factor (how the temperature is reduced between consecutive iterations
              coolingFactor: 0.95,

              // Lower temperature threshold (below this point the layout will end)
              minTemp: 1.0,

              // Pass a reference to weaver to use threads for calculations
              weaver: false
    };
    cy.add(graphElements);
    cy.layout(options); 
});

My page:
{% extends "queryapp/base.html" %}
{% block content %}
{% block title %}Default query page{% endblock %}
{% load static %}
<script>
var graphElements = {{ graph_elements|safe }};
</script>
<script src="{% static 'skimmr_django/js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'queryapp/js/cytoscape.js' %}"></script>
<script src="{% static 'queryapp/js/result.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'queryapp/css/result.css' %}" />

<div id="cy"></div>
{% endblock %}

graphElements is valid JSON I get from Python. 
Example (the whole thing is too big to post it all here):
{"grabbable": true, "data": {"label-size": 9, "width": 0.4, "color": "#6699CC", "id": "something_about_boy"}, "group": "nodes", "classes": "node-class"},
The graph works and is correct in Chrome, but the problem is the layout in Firefox does not work. What can I do to fix that?
EDIT:
I have tried Internet Explorer too, it does not work.

A:

The problem was that I have been following the introduction:
http://js.cytoscape.org/#getting-started/initialisation
Which does not tell you the following (from http://js.cytoscape.org/#notation/position):
position: { // the model position of the node (optional on init, mandatory after)
I don't care about the initial position of my nodes, so I did not add it. Note that I load the nodes into the graph and have no initial nodes. The initial nodes do not need the position, ones you load in do.
I added position to my Nodes (so it is now included in the JSON), and changed the Javascript (this is probably not necessary but I will add it just in case it is):
cy.add(graphElements);
var layout = cy.elements().layout(options);
layout.run();

It now works in both Firefox and Chrome.
If you run into this problem, add
position {
    x: 1,
    y: 1
}

to your nodes. If you run into this problem you either don't care about the initial position (like me) so you can use whatever or forgot to add the positions to your nodes.
After that, the layout will work.
If someone can explain why it works in Chrome (even though as I understand it shouldn't) I will accept that answer instead.

