0

Hullo, I am trying to present a simple two framed page by means of the PhoneGap Desktop application. The bottom frame constituted by a table is shown correctly everywhere, conversely the top one in which a graphic should be shown is correctly shown when I connect to a web version of it, both on my computer and iPhone, but when I try to access it by connecting through the PhoneGap app or with Safari on my iPhone to the local publication, the top screen is totally blank. I am using the NVD3 library for drawing the graph and I load the data for them by Ajax. What could be the issue and how may I debug it? This is the code of the page; the feeding web page is local and so you might not be able to execute it correctly:

<!DOCTYPE html>
<html>
<head>
   <style>
    text {
        font: 12px sans-serif;
    }
    svg {
        display: block;
        height: 75%;
    }
    html, body, #chart1, svg {
        margin: 0px;
        padding: 0px;
        height: 100%;
        width: 100%;
    }

    .dashed {
        stroke-dasharray: 5,5;
    }
</style>
<meta charset="utf-8">
<link href="../build/nv.d3.css" rel="stylesheet" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.2/d3.min.js" charset="utf-8"></script>
<script src="../build/nv.d3.js"></script>
<link href="drawer.css" rel="stylesheet" type="text/css">
<!-- <script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script> -->
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
<!-- This is a wide open CSP declaration. To lock this down for production, see below. -->
<!-- <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *" /> -->
<!-- Good default declaration:
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
* Disables use of eval() and inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
    * Enable inline JS: add 'unsafe-inline' to default-src
    * Enable eval(): add 'unsafe-eval' to default-src
* Create your own at http://cspisawesome.com
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: 'unsafe-inline' https://ssl.gstatic.com; style-src 'self' 'unsafe-inline'; media-src *" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
</head>
<body class='with-3d-shadow with-transitions'">
<input type="checkbox" id="drawer-toggle" name="drawer-toggle"/>
<label for="drawer-toggle" id="drawer-toggle-label"></label>
<header>Select</header>
<nav id="drawer">
    <div id="list">
    </div>
</nav>
<div id="page-content">
<div id="chart1"></div>
<script>
var chart;
var data;
var hiddenGraphNames=[];

nv.addGraph(function() {
alert("nv");
    loadJSON(function(response) {
        loadPipeNames(response);
        chart = nv.models.lineChart()
            .options({
                duration: 300,
                useInteractiveGuideline: true
            })
        ;

    // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
        chart.xAxis
            .axisLabel("Time (s)")
            .tickFormat(d3.format(',.1f'))
            .staggerLabels(true)
        ;

        chart.yAxis
            .axisLabel('Voltage (v)')
            .tickFormat(function(d) {
                if (d == null) {
                    return 'N/A';
                }
                return d3.format(',.2f')(d);
            })
        ;
        data = pipeGraphs(response);
        d3.select('#chart1').append('svg')
            .datum(data)
            .call(chart);

        nv.utils.windowResize(chart.update);

        return chart;
    })
});

String.prototype.strcmp = function(s) {
    if (this < s) return -1;
    if (this > s) return 1;
    return 0;
}

function load(){
    var parent=window.parent.document;
    var div=parent.getElementById('excludedPipes');
    var value=div.getAttribute('value');
    if (value.length>0){
        //alert("dentro");
        hiddenGraphNames = value.split(",");
    } else {
        //alert("resetto");
        hiddenGraphNames = [];
    }
}

function loadJSON(callback) {
    var xhr = new XMLHttpRequest();
    xhr.overrideMimeType("application/json");
    xhr.open('GET', 'http://materiali.c-s-m.it/phonegap/', true); // Replace 'my_data' with the path to your file
    xhr.onload = function (e) {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
        // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
                callback(xhr.responseText);
            } else {
                alert(xhr.statusText);
            }
        }
    };
    xhr.send(null);  
}

function save(){
    var parent=window.parent.document;
    var div=parent.getElementById('excludedPipes');
    div.setAttribute('value', hiddenGraphNames);
}



function pipeGraphs(response){
    load();
    var collection=[];
    var actual_JSON = JSON.parse(response);
    for (i in actual_JSON){
        var values=[];
        var element=actual_JSON[i];
        var graph=element.graph;
        var color=graph.color;
        var key=graph.name;
        var present=hiddenGraphNames.filter(function(e) { return e == key })
        if (present.length>0){
            setHiddenColor(true, key);
            continue;
        }
        var j=0;
        graph.values.forEach(function(value){
            values.push({x: j, y: value});
            j++;
        });
        collection.push({
            area: false,
            values: values,
            key: key,
            color: color,
            strokeWidth: 4
        });
    }
    //logValues(collection[0].values)
    return collection;
}

function sinAndCos() {
    var sin = [],
        sin2 = [],
        cos = [],
        rand = [],
        rand2 = []
        ;

    for (var i = 0; i < 100; i++) {
        sin.push({x: i, y: i % 10 == 5 ? null : Math.sin(i/10) }); //the nulls are to show how defined works
        sin2.push({x: i, y: Math.sin(i/5) * 0.4 - 0.25});
        cos.push({x: i, y: .5 * Math.cos(i/10)});
        rand.push({x:i, y: Math.random() / 10});
        rand2.push({x: i, y: Math.cos(i/10) + Math.random() / 10 })
    }

    return [
        {
            area: true,
            values: sin,
            key: "Sine Wave",
            color: "#ff7f0e",
            strokeWidth: 4,
            classed: 'dashed'
        },
        {
            values: cos,
            key: "Cosine Wave",
            color: "#2ca02c"
        },
        {
            values: rand,
            key: "Random Points",
            color: "#2222ff"
        },
        {
            values: rand2,
            key: "Random Cosine",
            color: "#667711",
            strokeWidth: 3.5
        },
        {
            area: true,
            values: sin2,
            key: "Fill opacity",
            color: "#EF9CFB",
            fillOpacity: .1
        }
    ];
}
function composeAttributes(strings){
    var output="?";
    for (var i in strings){
        var string=strings[i];
        output+="=1&";
    }
    return output;
}

function setHiddenColor(hidden, name){
    var aHref=document.getElementById(name);
    if (hidden){
        aHref.setAttribute("style", "color:FF0000"); //disable
        //alert("rosso"+aHref);
    } else {
        aHref.setAttribute("style", "color:#FFFFFF"); //enable
    }
}

function toggle(name){
    var present=hiddenGraphNames.filter(function(e) { return e == name })
    if (present.length==0){ //was enabled
        hiddenGraphNames.push(name);
    } else {
        hiddenGraphNames = hiddenGraphNames.filter(function(e) { return e !== name })
    }
    save();
    location.reload();
}

function loadPipeNames(response){
    var menu="<ul>";
    var actual_JSON = JSON.parse(response);
    for (var i in actual_JSON){
        var values=[];
        var element=actual_JSON[i];
        var graph=element.graph;
        var name=graph.name;
        var present=hiddenGraphNames.filter(function(e) { return e == key })
        if (present.length>0){
            continue;
        }
        menu+="<li><a id='"+name+"' href=\"#\" onclick=\"toggle('"+name+"');\">"+name+"</a></li>";
    }
    menu+="</ul>";
    var div=document.getElementById("list");
    div.innerHTML=menu;
}

function myMenu(){
    loadJSON(function(response) {
        loadPipeNames(response)
    });
}

An error I see on the Chrome console is: index.js:41 Uncaught TypeError: Cannot read property 'querySelector' of null(…)

Fabrizio Bartolomucci
  • 4,948
  • 8
  • 43
  • 75
  • Have you tried the chrome device emulator? You can toggle it in chrome tools with "Toggle device toolbar" in the top left once the dev console is active. With safari you can also inspect pages on your actual iOS device. – Jacksonkr Nov 24 '16 at 15:29
  • Unfortunately I have the Italian Chome version and I have no cue where the Chrome tools are. Yet the problem is that the page loads fine when I access it by browser on a web server, the problem comes when it is erogated by the PhoneGap framework both if I access it by their iOS App or by connecting to the published page. I thereafter suspect PhoneGap not to correctly show the content rather than being a browser problem. – Fabrizio Bartolomucci Nov 24 '16 at 15:37
  • haha, [try this](https://developers.google.com/web/tools/chrome-devtools/device-mode/) – Jacksonkr Nov 24 '16 at 15:39
  • Ok, yet I would not know what to simulate. The web version works fine even on my iPhone, why the page published by PhoneGap Desktop is shown nowhere! – Fabrizio Bartolomucci Nov 24 '16 at 15:45

1 Answers1

0

The issue was due to a problem on my iPhone that had the DNS configured to an external server while the server to be connected to is internal.

Fabrizio Bartolomucci
  • 4,948
  • 8
  • 43
  • 75